This API allows to work with your app data, execute actions, check status of jobs, logs, etc., all through a simple REST interface. Everything that can be done from the UI in an app can also be done using these web services.
Slingr API is based on REST recommendations (we don’t follow all of them though) and we use JSON as the main data format.
You can access the API at the following URL:
https://<appName>.slingrs.io/<env>/runtime/api
where appName
is the name of the app and env
is the name of the environment, like dev
and prod
.
Notice that you always have to use HTTPS. Trying to access out API using HTTP will return an error.
Additionally, all calls should have the following headers:
Content-Type: application/json
Accept: application/json
token: <token received after login>
General error codes
Here are some general error descriptions. Then on each method you will see a better description to some of the errors that can show up.
HTTP Status Code | Description |
---|---|
|
Everything went fine. No errors. |
|
Request is not valid. This can be due to validation errors in the data you are sending or because the operation you are trying to do is not valid. |
|
Unauthorized. You need to log in or the provided token is not valid. |
|
Forbidden. You have credentials, but you are trying to access data or execute an operation you don’t have permissions. |
|
Not found. The resource you are trying to access does not exist. |
|
Optimistic locking exception. This happens when two users tries to update the same record at the same time. The once that enters in the second place will get this error. |
|
Internal error. This happens when something went wrong and was not expected. If you get this type of errors please contact support. |
|
Service unavailable. This is when the application is under maintenance. |
Authentication
Before being able to use the API, you need to log in and get a valid token. The URL to get the token is the following:
POST /auth/login
This method has no parameters and the body should have the following form:
{
"email": "user@test.com",
"password": "abcdefgh"
}
The response will be something like this:
{
"app": "appname",
"adminUserEmail": null,
"ip": "::ffff:10.240.0.38",
"userEmail": "user@test.com",
"userName": "User Test",
"userId": "57fce0c3e4b0ce322b0c06b2",
"token": "eLJjYSjLUPLlIEe8lfJUOmzsVNvSRpOv"
}
HTTP Status Code | Description |
---|---|
|
Code of the app the token belongs to. |
|
This field is used when impersonating another user. Please read more on the following section. |
|
The IP the user logged in from. |
|
The email of the user you have logged in with. |
|
The full name of the user you have logged in with. |
|
The ID of the user you have logged in with. |
|
This is the most important field and contains the token you will need to use in any further call to the API. This token might expire, so you need to keep that in mind when coding your integration. |
Once you have the token, you have to send it over the header of every request. For example:
GET /data/companies
> Accept: application/json
> token: eLJjYSjLUPLlIEe8lfJUOmzsVNvSRpOv
When the token expires (usually after 8 hours of inactivity, but could be less due to maintenance or other
internal tasks) you will get a 401
error and you need to login again.
Impersonating other users
Developer users or users with the flag to manage groups have the ability to impersonate other users. In order to do that, when logging in the following body should be sent:
{
"email": "manager@test.com",
"password": "manager_password",
"emailImpersonatedUser": "employee@test.com"
}
The response will be something like this:
{
"app": "appname",
"adminUserEmail": "manager@test.com",
"ip": "::ffff:10.240.0.39",
"userEmail": "employee@test.com",
"userName": "Employee Test",
"userId": "57fe52ade4b0ce322b0cea32",
"token": "NE8lUuA2Yi9K6gL9EaQaTLIQLvYIhIyv"
}
You can notice that the adminUserEmail
field contains now the email of the manager user that is
impersonating employee@test.com
.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Thrown when credentials are invalid. This can be either the user email does not exist or password does not match. |
|
|
The user you are trying to impersonate does not exist. |
|
|
If credentials are valid but you are not allowed to log in. For example, this can happen when there are IP restrictions. Another case is that you are trying to impersonate a user and you don’t have enough permissions. |
|
|
Malformed request. For example, you didn’t provide |
|
|
If the application is suspended or in maintenance mode. Developer users should be able to log in anyway. |
App data
For each entity in the app, a set of methods will be automatically created. For example if there is
an entity called companies
, the following methods will be available:
GET /data/companies
GET /data/companies/{id}
PUT /data/companies/{id}
POST /data/companies
DELETE /data/companies/{ids}
These are the basic operations for each entity that allow to list, read, update, create and delete records.
The content of the data will be dictated by the structure of the fields in the entity. For example getting a company record will return something like this:
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 379,
"label": "Browsezoom",
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485012900000
}
There are basically two types of fields:
- Record fields: these are the fields defined in the entity. The format for them depends on the type of the field. You should check the types documentation.
- System fields: they are always there. These are:
id
: the ID of the record.label
: this is the label of the record based on the instance label expression defined in the entity.version
: the version of the record that will be used for optimistic locking.
Basic operations
Read one record
GET /data/{entityName}/{id}
Reads one record by ID.
Request
GET /data/{entityName}/{id}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
ID of the record to fetch. |
|
|
no |
|
By default all fields will be fetched. If you want to specify which fields you want to fetch, you can pass this parameter. You can specify many fields separating them by commas:
System field will always be returned ( |
|
no |
|
The format to use to fetch the fields. There are two options: |
|
no |
A comma-separated list of relationship fields that will be fetched within the record. For example
if an entity has relationship fields named
|
Response
The JSON representation of the record is returned. More info about the format can be found here.
GET /data/{entityName}/{id}
< Content-Type: application/json
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 1,
"label": "label",
"fieldA": "value",
"fieldB": "value"
"fieldC": "value"
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Provided token does not have permissions to access this record. |
|
|
Either entity or record ID does not exist. |
Samples
fetches one company record
GET /data/companies/57fd2d65e4b0ce322b0c8665
> Accept: application/json
> token: token
GET /data/companies/57fd2d65e4b0ce322b0c8665
< Content-Type: application/json
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 379,
"label": "Browsezoom",
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485012900000
}
List records
GET /data/{entityName}
Reads many records from one entity. You can specify filters and other options in the URL.
More information about queries can be found in Query language.
Request
GET /data/{entityName}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
no |
You can find information about other parameters in Query language. |
Response
A list of records in JSON representation will be returned.
GET /data/{entityName}
< Content-Type: application/json
{
"total": 10,
"offset": "57fd2d65e4b0ce322b0c8565",
"items": [
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 1,
"label": "label",
"fieldA": "value",
"fieldB": "value"
},
{
"id": "57fd2d65e4b0ce322b0c8565",
"version": 1,
"label": "label",
"fieldA": "value",
"fieldB": "value"
}
]
}
Path | Description |
---|---|
|
The total number of records matched. If there are more than the records returned, you should use pagination to fetch more records. See Limit size and Skip records. |
|
The offset to pass to get more records. Please see Skip records. |
|
This is the list of records fetched. For more information about the format of records, please go here. |
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Query is not valid. |
|
|
Provided token does not have permissions to access this entity or some of the fields you are querying by. |
|
|
If entity name does not exist. |
Samples
fetches fields name and type of two companies in pending status
GET /data/companies?state=pending&_fields=name,type&_size=2
> Accept: application/json
> token: token
GET /data/companies?state=pending&_fields=name,type&_size=2
< Content-Type: application/json
{
"total": 135,
"offset": "57fd2d65e4b0ce322b0c8565",
"items": [
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 379,
"label": "Browsezoom",
"name": "Browsezoom",
"type": "a"
},
{
"id": "57fd2d65e4b0ce322b0c8565",
"version": 375,
"label": "Blogpad",
"name": "Blogpad",
"type": "b"
}
]
}
Create record
POST /data/{entityName}
Creates a new record for the given entity.
Data is sent in the body and should be valid according to the entity structure and fields rules.
Request
The body of this request should be a record in JSON format based on the entity structure.
All fields you are sending have to be present in the entity definition and values have to match the format required by the type (see Types). Also, there might be validation rules you have to take into account.
POST /data/{entityName}
> Content-Type: application/json
> Accept: application/json
> token: token
{
"fieldA": "value",
"fieldB": "value"
"fieldC": 10,
"nestedFields": [
{
"innerA": "value",
"innerB": "value"
},
{
"innerA": "value",
"innerB": "value"
}
]
}
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record will be added to. |
Response
The response is the same as if you do a GET /data/companies/{id}
, which means that you will be able
to get the ID and label of the created record, as well as other calculated/default fields the entity
might have.
You can find more information about the JSON format of a record here.
POST /data/{entityName}
< Content-Type: application/json
{
"id": "588775f63b063a0007604f4c",
"version": 0,
"label": "label",
"fieldA": "value",
"fieldB": "value"
"fieldC": 10,
"nestedFields": [
{
"id": "588775f63b063a0007604f4c",
"label": "label",
"innerA": "value",
"innerB": "value"
},
{
"id": "588775f63b063a0007604f8a",
"label": "label",
"innerA": "value",
"innerB": "value"
}
],
"calculatedField": "value"
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If there are validations errors, the response will look like this:
In this case you will get details information about the field having issues, the error code and a human readable description of the error. Additional information might be added depending on the type of error, for example the rejected value. |
|
|
Provided token does not have permissions to create records on this entity. |
|
|
If entity name does not exist. |
Samples
creates a new company
POST /data/companies
> Content-Type: application/json
> Accept: application/json
> token: token
{
"name": "Test 1",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "test notes",
"lastMeeting": 1429623180000
}
POST /data/companies
< Content-Type: application/json
{
"id": "588775f63b063a0007604f4c",
"version": 0,
"label": "Test 1",
"name": "Test 1",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "588775f63b063a0007604f4a",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "588775f63b063a0007604f4b",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "test notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485272566096
}
Update record
PUT /data/{entityName}/{id}
Updates a record data.
Data is sent in the body and should be valid according to the entity structure and fields rules.
Request
The body of this request should be a record in JSON format based on the entity structure.
All fields you are sending have to be present in the entity definition and values have to match the format required by the type (see Types). Also, there might be validation rules you have to take into account.
You can specify only the fields you want to set. Fields that are not included won’t be modified
(if you want to clear a field value, set them to null
explicitly).
One important thing to mention here is the field version
, which indicates the version of the record you are
updating. This is to handle concurrency issues when two users try to update the same record at the same time
(read the optimistic locking section below). If you don’t provide the version
field then you will always
write the data, no matter if you are overriding other user’s data.
PUT /data/{entityName}/{id}
> Content-Type: application/json
> Accept: application/json
> token: token
{
"version": 1,
"fieldA": "newValue",
"fieldB": "newValue",
"nestedFields": [
{
"id": "588775f63b063a0007604f4c",
"innerA": "newValue"
},
{
"id": "588775f63b063a0007604f8a",
"innerB": "newValue"
}
]
}
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
The ID of the record to update. If you provide the ID on the body it will be discarded and the ID sent in the URL parameter will be used. |
Response
The response is the same as if you do a GET /data/companies/{id}
, which means that you will
be able to get the ID and label of the updated record, as well as other calculated/default fields
the entity might have.
PUT /data/{entityName}/{id}
< Content-Type: application/json
{
"id": "588775f63b063a0007604ab2",
"version": 0,
"label": "label",
"fieldA": "newValue",
"fieldB": "newValue"
"fieldC": 10,
"nestedFields": [
{
"id": "588775f63b063a0007604f4c",
"label": "label",
"innerA": "newValue",
"innerB": "value"
},
{
"id": "588775f63b063a0007604f8a",
"label": "label",
"innerA": "value",
"innerB": "newValue"
}
],
"calculatedField": "value"
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If there are validations errors, the response will look like this:
In this case you will get details information about the field having issues, the error code and a human readable description of the error. Additional information might be added depending on the type of error, for example the rejected value. |
|
|
Provided token does not have permissions to edit records on this entity or you don’t have permissions to edit this particular record. |
|
|
If entity name or record ID does not exist. |
|
|
If another user modified the data in the middle. This can be determined only if you provide the
|
Samples
updates a few fields in a company record
PUT /data/companies/588775f63b063a0007604f4c
> Content-Type: application/json
> Accept: application/json
> token: token
{
"version": 1,
"state": "active",
"type": "b",
"numberOfEmployees": 100
}
PUT /data/companies/588775f63b063a0007604f4c
< Content-Type: application/json
{
"id": "588775f63b063a0007604f4c",
"version": 2,
"label": "Test 1",
"name": "Test 1",
"state": "active",
"type": "b",
"numberOfEmployees": 100,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "588775f63b063a0007604f4a",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "588775f63b063a0007604f4b",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "test notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485288240000
}
Delete one record
DELETE /data/{entityName}/{id}
Deletes a record from the database. You won’t be able to recover the deleted record (except that you have enabled history for that entity).
Request
DELETE /data/{entityName}/{id}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
ID of the record to delete. |
|
|
no |
Indicates if the delete has to be executed in the background, which is needed if the execution is going to take more than 30 seconds. When setting this parameter to |
Response
The response will be different based on the parameter async
. There are two possible responses:
- Record: if the
async
parameter isfalse
, then the deleted record is returned by this method. - Job reference: if the
async
parameter istrue
, the method will return a reference to the job in charge of the execution of the delete process. Once the job is completed you will find the response of the process in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Provided token does not have permissions to delete this record. |
|
|
Either entity or record ID does not exist. |
Samples
deletes one company
DELETE /data/companies/588775f63b063a0007604f4c
> Accept: application/json
> token: token
DELETE /data/companies/588775f63b063a0007604f4c
< Content-Type: application/json
{
"id": "588775f63b063a0007604f4c",
"version": 10,
"label": "Test 1",
"name": "Test 1",
"state": "active",
"type": "b",
"numberOfEmployees": 100,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "588775f63b063a0007604f4a",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "588775f63b063a0007604f4b",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "test notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485288240000
}
deletes one company in the background
DELETE /data/companies/588775f63b063a0007604f4c?_async=true
> Accept: application/json
> token: token
DELETE /data/companies/588775f63b063a0007604f4c?_async=true
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/5887b6f23b063a0007604fa8",
"jobId": "5887b6f23b063a0007604fa8"
}
Delete many records
DELETE /data/{entityName}/{ids}
Deletes many records from the database. You won’t be able to recover deleted records (except that you have enabled history for that entity).
This method will return immediately but a job will be created to delete the records in the background. You can check the status of the job to verify when it finishes.
Request
DELETE /data/{entityName}/{ids}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity records belongs to. |
|
|
yes |
IDs of records to delete separated by commas. |
|
|
no |
Indicates if the delete has to be executed in the background, which is needed if the execution is going to take more than 30 seconds or you want to delete more than 1,000 records. When setting this parameter to |
Response
The response will be different based on the parameter _async
. There are two possible responses:
- A map with records: if the
_async
parameter isfalse
, then the result will be a map with the ID of the record as the key and the value will be a map with the fieldsstatus
andresponse
(the deleted record as a JSON) or errorMessage if there was an error. - Job reference: if the
_async
parameter istrue
, the method will return a reference to the job in charge of the execution of the delete process. Once the job is completed you will find the response of the process in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Provided token does not have permissions to delete records on this entity. |
|
|
If the entity name does not exist. |
Samples
deletes two companies
DELETE /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
> Accept: application/json
> token: token
DELETE /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8665",
"version": 381,
"label": "Browsezoom",
"entity": {
"id": "57fce228e4b0f6600fdfb836",
"name": "Companies"
},
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com"
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145",
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485292080000
}
},
"57fd2d65e4b0ce322b0c8565": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8565",
"version": 377,
"label": "Blogpad",
"name": "Blogpad",
"state": "pending",
"type": "b",
"numberOfEmployees": 534,
"isCustomer": false,
"contactInformation": {
"id": "581224c8e4b0285870237cc5",
"label": "Contact Information",
"phoneNumber": "1-405-298-5885",
"email": "molsonre@rakuten.co.jp"
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86ac",
"label": "OK - 73157",
"addressLine": "4 Crownhardt Plaza",
"zipCode": "73157",
"city": "Oklahoma City",
"state": "OK"
}
],
"homepage": "http://www.blogpad.com",
"taxId": "123-ABC",
"rating": "3.3",
"notes": "Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.",
"lastMeeting": 1422111300000,
"lastUpdate": 1485292500000
}
}
}
deletes two companies in the background
DELETE /data/companies/588775f63b063a0007604f4c,588775f63b063a0007604f8b?_async=true
> Accept: application/json
> token: token
DELETE /data/companies/588775f63b063a0007604f4c,588775f63b063a0007604f8b?_async=true
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/5887b6f23b063a0007604fa8",
"jobId": "5887b6f23b063a0007604fa8"
}
Delete records over query
DELETE /data/{entityName}
Deletes all records matched by a query. You won’t be able to recover deleted records (except that you have enabled history for that entity).
This method will return immediately but a job will be created to delete the records in the background. You can check the status of the job to verify when it finishes.
Request
DELETE /data/{entityName}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity records belongs to. |
|
|
no |
These are the query parameters. See Query language for more information. |
|
|
no |
Indicates if the delete has to be executed in the background, which is needed if the execution is going to take more than 30 seconds or you want to delete more than 1,000 records. When setting this parameter to |
|
|
no |
Sets job as low priority will make the deletion only happen when there are no many jobs running. |
|
|
no |
|
If |
|
no |
|
If |
Response
The response will be different based on the parameter _async
. There are two possible responses:
- A map with records: if the
_async
parameter isfalse
, then the result will be a map with the ID of the record as the key and the value will be a map with the fieldsstatus
andresponse
(the deleted record as a JSON) or errorMessage if there was an error. - Job reference: if the
_async
parameter istrue
, the method will return a reference to the job in charge of the execution of the delete process. Once the job is completed you will find the response of the process in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Provided token does not have permissions to delete records on this entity. |
|
|
If the entity name does not exist. |
Samples
deletes companies with type 'a'
DELETE /data/companies?type=a
> Accept: application/json
> token: token
DELETE /data/companies?type=a
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8665",
"version": 381,
"label": "Browsezoom",
"entity": {
"id": "57fce228e4b0f6600fdfb836",
"name": "Companies"
},
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com"
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145",
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485292080000
}
}
}
deletes companies with type 'a' in the background
DELETE /data/companies?_async=true&type=a
> Accept: application/json
> token: token
DELETE /data/companies?_async=true&type=a
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/5887b6f23b063a0007604fa8",
"jobId": "5887b6f23b063a0007604fa8"
}
Optimistic locking
Optimistic locking is a feature that helps to avoid overwriting changes made by other users in a record. To do that it uses the record version, which is a number that increases every time there is a change in a record.
When updating a record, if you send the field version
as part of the
body, and that version doesn’t match the version of the record in the server,
a 409 error will be returned. This prevents changes made by other users to be
overwritten.
If the field version
is not sent, then no version control will be done
and you might end up overwriting changes from other users, so it is strongly
recommended to use it when updating records.
Aggregate queries
PUT /data/{entityName}/aggregate
You can perform aggregation operations like count, sum or average.
For detailed documentation please check Aggregate queries.
Request
The request’s body contains the chain of operations to execute over the entity records. For more information please check documentation for Aggregate queries.
PUT /data/{entityName}/aggregate
> Content-Type: application/json
> Accept: application/json
> token: token
[
{"operation1": "settings"},
{"operation2": "settings"},
{"operationN": "settings"}
]
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
Response
The result of the aggregation is returned. The format is specific to the aggregation done, so please check the documentation for Aggregate queries.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
Aggregation query is not valid. |
|
|
You are trying to aggregate data you don’t have permissions to read. This applies at the entity level, record level and field level. |
Samples
counts the number of skills per company
PUT /data/contacts/aggregate
> Content-Type: application/json
> Accept: application/json
> token: token
[
{"project": "company,numberOfSkills"},
{"group": {"by": "company", "totalSkills": "sum(numberOfSkills)"}}
]
PUT /data/contacts/aggregate
< Content-Type: application/json
{
"total": 6,
"items": [
{
"company": "Trudoo",
"totalSkills": 1
},
{
"company": "Riffwire",
"totalSkills": 3
},
{
"company": "Snaptags",
"totalSkills": 2
},
{
"company": "Edgeify",
"totalSkills": 0
},
{
"company": "Flipopia",
"totalSkills": 3
},
{
"company": "Rooxo",
"totalSkills": 4
}
}
]
Actions
Execute action over one record
PUT /data/{entityName}/{id}/{actionName}
Execute an action over one record.
Request
If the action contains parameters, you can send them in the body. The format is the same as when you create or update records, but instead of fields you should send parameters of the action.
If the action doesn’t have parameters you can leave the body empty.
PUT /data/{entityName}/{id}/{actionName}
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "value",
"param2": value
}
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
ID of the record to execute the action on. |
|
|
yes |
The name of the action that has to be executed. |
|
|
no |
Indicates if the action has to be executed in the background, which is needed if the execution is going to take more than 30 seconds. When setting this parameter to This parameter will override the default configured in the action. |
Response
The response will be different based on the type of action and the parameter _async
. There are three
possible responses:
- Record: if the
_async
parameter isfalse
and the action doesn’t return any custom response, then the updated record is returned by this method. This only applies for actions of typeOne record
. - Custom action’s response: if the
_async
parameter isfalse
and the action returns a custom response, then that response is returned. Keep in mind that actions of typeMany records
should always return a custom response. If they don’t return anything, an empty response will be returned. - Job reference: if the
_async
parameter istrue
, the method will return a reference to the job in charge of the execution of the action. Once the action is completed you will find the response of the action in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If request is not allowed. For example, pre-conditions in the actions are not met. |
|
|
You don’t have permissions to execute the action or you don’t have permissions for the record. |
|
|
The entity name or the record does not exist. |
Samples
executes a simple action over a company record, no custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665/logSomething
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/57fd2d65e4b0ce322b0c8665/logSomething
< Content-Type: application/json
{
"id": "57fd2d65e4b0ce322b0c8665",
"version": 381,
"label": "Browsezoom",
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"id": "58837fdd3b063a0007603547",
"label": "Contact Information",
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145",
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485292080000
}
executes a simple action over a company record in the background, no custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665/logSomething?_async=true
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/57fd2d65e4b0ce322b0c8665/logSomething?_async=true
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f3e65b45fc9000bc1baa7",
"jobId": "588f3e65b45fc9000bc1baa7"
}
executes an action that works with many records and returns a custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665/countEmployees
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/57fd2d65e4b0ce322b0c8665/countEmployees
< Content-Type: application/json
{
"numberOfEmployees": 95
}
Execute action over many records
PUT /data/{entityName}/{ids}/{actionName}
Execute an action over many records. The action will be executed in each record one by one if the action is
of type One record
.
Request
If the action contains parameters, you can send them in the body. The format is the same as when you create or update records, but instead of fields you should send parameters of the action.
If the action doesn’t have parameters you can leave the body empty.
PUT /data/{entityName}/{ids}/{actionName}
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "value",
"param2": value
}
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the records belongs to. |
|
|
yes |
IDs of records to execute the action on separated by commas. |
|
|
yes |
The name of the action that has to be executed. |
|
|
no |
Indicates if the action has to be executed in the background, which is needed if the execution is going to take more than 30 seconds or if it is applied over more than 1,000 records. When setting this parameter to This parameter will override the default configured in the action. |
Response
The response will be different based on the type of action and the parameter _async
. There are three
possible responses:
- A map with records: if the
_async
parameter isfalse
and the action doesn’t return any custom response, then the result will be a map with the ID of the record as the key and the value will be a map with the fieldsstatus
andresponse
(the record as a JSON) or errorMessage if there was an error. This only applies for actions of typeOne record
. - Custom action’s responses: if the
_async
parameter isfalse
and the action returns a custom response, then a map with the ID of the record (for each record) as key and a map with thestatus
(“ok” or “error”) andresponse
with the custom response will be returned. Keep in mind that actions of typeMany records
should always return a custom response. If they don’t return anything, an empty response will be returned. - Job reference: if the
_async
parameter istrue
, the method will return a reference to the job in charge of the execution of the action. Once the action is completed you will find the response of the action in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
You don’t have permissions to execute the action. |
|
|
If the entity name does not exist. |
Samples
executes a simple action over two company records, no custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/logSomething
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/logSomething
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8665",
"version": 381,
"label": "Browsezoom",
"entity": {
"id": "57fce228e4b0f6600fdfb836",
"name": "Companies"
},
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com"
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145",
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485292080000
}
},
"57fd2d65e4b0ce322b0c8565": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8565",
"version": 377,
"label": "Blogpad",
"name": "Blogpad",
"state": "pending",
"type": "b",
"numberOfEmployees": 534,
"isCustomer": false,
"contactInformation": {
"id": "581224c8e4b0285870237cc5",
"label": "Contact Information",
"phoneNumber": "1-405-298-5885",
"email": "molsonre@rakuten.co.jp"
},
"addresses": [
{
"id": "57fd45aee4b0ce322b0c86ac",
"label": "OK - 73157",
"addressLine": "4 Crownhardt Plaza",
"zipCode": "73157",
"city": "Oklahoma City",
"state": "OK"
}
],
"homepage": "http://www.blogpad.com",
"taxId": "123-ABC",
"rating": "3.3",
"notes": "Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.",
"lastMeeting": 1422111300000,
"lastUpdate": 1485292500000
}
}
}
executes a simple action over two company records with custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/customResponse
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/customResponse
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": "This is a custom response"
},
"57fd2d65e4b0ce322b0c8565": {
"status": "ok",
"response": "This is a custom response"
}
}
executes a simple action over two company records in the background
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/logSomething?_async=true
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/logSomething?_async=true
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f45e2b45fc9000bc1bd1f",
"jobId": "588f45e2b45fc9000bc1bd1f"
}
executes an action that works with many records over two records and returns a custom response
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/countEmployees
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565/countEmployees
< Content-Type: application/json
{
"numberOfEmployees": 629
}
Execute action over query
PUT /data/{entityName}/{actionName}
Execute an action over records matched by a query.
Request
If the action contains parameters, you can send them in the body. The format is the same as when you create or update records, but instead of fields you should send parameters of the action.
If the action doesn’t have parameters you can leave the body empty.
PUT /data/{entityName}/{actionName}
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "value",
"param2": value
}
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the records belongs to. |
|
|
yes |
IDs of records to execute the action on separated by commas. |
|
|
yes |
The name of the action that has to be executed. |
|
|
no |
Indicates if the action has to be executed in the background, which is needed if the execution is going to take more than 30 seconds or if it is applied over more than 1,000 records. When setting this parameter to This parameter will override the default configured in the action. |
|
|
no |
These are the query parameters. See Query language for more information. |
Response
The response will be different based on the type of action and the parameter _async
. There are three
possible responses:
- A map with records: if the
_async
parameter isfalse
and the action doesn’t return any custom response, then a map with the ID of the records as key and the JSON of the records as value will be returned. This only applies for actions of typeOne record
. - Custom action’s responses: if the
_async
parameter isfalse
and the action returns a custom response, then a map with the ID of the record (for each record) as key and a map with thestatus
(“ok” or “error”) andresponse
with the custom response will be returned. Keep in mind that actions of typeMany records
should always return a custom response. If they don’t return anything, an empty response will be returned. - Job reference: if the
_async
parameter istrue
, the method will return a reference to the job in charge of the execution of the action. Once the action is completed you will find the response of the action in the results of the job.
You can find samples for each type of response below.
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
You don’t have permissions to execute the action. |
|
|
If the entity name does not exist. |
Samples
executes a simple action over two company records, no custom response
PUT /data/companies/logSomething?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/logSomething?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8665",
"version": 381,
"label": "Browsezoom",
"entity": {
"id": "57fce228e4b0f6600fdfb836",
"name": "Companies"
},
"name": "Browsezoom",
"state": "pending",
"type": "a",
"numberOfEmployees": 95,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-702-845-9380",
"email": "jwoodsrq@spotify.com",
"id": "58837fdd3b063a0007603547",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Magdeline Place",
"zipCode": "89145",
"city": "Las Vegas",
"state": "NV",
"id": "57fd45aee4b0ce322b0c86aa",
"label": "NV - 89145"
}
],
"homepage": "http://www.browsezoom.com",
"taxId": "350-KWM",
"rating": "2.8",
"notes": "modified notes",
"lastMeeting": 1429623180000,
"lastUpdate": 1485292080000
}
},
"57fd2d65e4b0ce322b0c8565": {
"status": "ok",
"response": {
"id": "57fd2d65e4b0ce322b0c8565",
"version": 377,
"label": "Blogpad",
"name": "Blogpad",
"state": "pending",
"type": "b",
"numberOfEmployees": 534,
"isCustomer": false,
"contactInformation": {
"phoneNumber": "1-405-298-5885",
"email": "molsonre@rakuten.co.jp",
"id": "581224c8e4b0285870237cc5",
"label": "Contact Information"
},
"addresses": [
{
"addressLine": "4 Crownhardt Plaza",
"zipCode": "73157",
"city": "Oklahoma City",
"state": "OK",
"id": "57fd45aee4b0ce322b0c86ac",
"label": "OK - 73157"
}
],
"homepage": "http://www.blogpad.com",
"taxId": "123-ABC",
"rating": "3.3",
"notes": "Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.",
"lastMeeting": 1422111300000,
"lastUpdate": 1485292500000
}
}
}
executes a simple action over two company records with custom response
PUT /data/companies/customResponse?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/customResponse?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
< Content-Type: application/json
{
"57fd2d65e4b0ce322b0c8665": {
"status": "ok",
"response": "This is a custom response"
},
"57fd2d65e4b0ce322b0c8565": {
"status": "ok",
"response": "This is a custom response"
}
}
executes a simple action over two company records in the background
PUT /data/companies/logSomething?_async=true&id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
> Content-Type: application/json
> Accept: application/json
> token: token
{
"param1": "a",
"param2": "b"
}
PUT /data/companies/logSomething?_async=true&id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f45e2b45fc9000bc1bd1f",
"jobId": "588f45e2b45fc9000bc1bd1f"
}
executes an action that works with many records over two records and returns a custom response
PUT /data/companies/countEmployees?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/countEmployees?id=57fd2d65e4b0ce322b0c8665,57fd2d65e4b0ce322b0c8565
< Content-Type: application/json
{
"numberOfEmployees": 629
}
Import records
POST /data/{entityName}/import
Imports records from a CSV file.
Request
Imports records from a CSV file. The CSV file should follow these rules:
- Headers: they have to be the path of the field you want to import. For example a field at the root of the
entity called
name
should havename
as header. If there is a nested field you should put the full path, likeaddress.state
. For multi-valued fields you need to put the index, for examplephoneNumbers[0]
orphoneNumbers[1]
. - Data format: based on the type of the field you need to use different formats. Please check the documentation for each type.
Usually an easy way to get a template of the CSV file is by exporting existing records using fields’ names instead of labels.
Records will be created if they didn’t exist. If they already exist, they will be updated. In order to determine if the record exists a unique field must be in the headers. If there are many the first one will be used.
It is also possible to import records in related entities as well. For example you have a contacts
entity
that has a relationship called company
that points to the companies
entity. Then you could have the
following headers in the CSV file:
company.name,company.type,firstName,lastName,email
So headers company.name
and company.type
are fields in the companies
entity. The import process will
try to match an existing company by name (assuming name
is a unique field) and will update its type
field.
If there is no match, a new record will be created in companies
and will be associated to the record in
contacts
. In this way you can create records in many entities with just one import.
The import will happen in a background job.
POST /data/{entityName}/import
> Content-Type: multipart/form-data
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
this is a multi-part with the CSV file to import. |
|
|
no |
The import will be done only when there aren’t many other jobs running at the same time. This is important for big imports if you don’t want to delay other jobs. |
|
|
no |
|
In order to speed up big imports you can decide to skip calculated fields. This means calculated fields might not have the correct value but you can calculate them later. This options is only available for developers. |
|
no |
|
If the import updates the label of the record and the record was referenced by another record, a cascade update will be done to update the label in the reference. If you want to speed up big imports you might decide to disable this feature. This options is only available for developers. |
|
no |
|
If you send This options is only available for developers. |
|
no |
|
Indicates if fields should be filtered by access rules. If disabled all fields will be imported no matter if they are accessible or not. Disabling this feature might have a slight performance improvement during imports. This options is only available for developers. |
|
no |
|
If set to This options is only available for developers. |
|
no |
|
There could be listeners for events associated to the creation or update of records. If this flag is set to
This options is only available for developers. |
|
no |
|
If set to This options is only available for developers. |
|
no |
|
If set to This options is only available for developers. |
|
no |
|
Updating or creating records through imports could trigger many cascade operation to update copied fields,
aggregate fields, etc. If you don’t want it to happen you can set this to This options is only available for developers. |
|
no |
|
Normally records with invalid fields (validation errors) won’t be created/updated. However, if this flag is
set to This options is only available for developers. |
Response
A reference to the job in charge of perform the import.
POST /data/{entityName}/import
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f8357b45fc9000bc1bd2a",
"jobId": "588f8357b45fc9000bc1bd2a"
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
You don’t have permissions to import records on this entity. |
|
|
The entity name does not exist. |
Samples
imports a few companies from a CSV file
POST /data/companies/import
> Content-Type: multipart/form-data
> Accept: application/json
> token: token
name,type
test1,a
test2,b
test3,c
POST /data/companies/import
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f3e65b45fc9000bc1baa7",
"jobId": "588f3e65b45fc9000bc1baa7"
}
Export records
PUT /data/{entityName}/export
Exports records to a CSV file. It is possible to filter records to export using a query and just export some of the fields.
You can use the _fields
parameter to indicate which fields should be included in the export. It works
very similar as in queries,
however there are a few differences:
- You can put related fields, that is fields that are in the entities pointed by relationship fields. For
example if you have a relationship field
company
pointing to thecompanies
entity, you could specify the fieldcompany.type
to be included in the CSV file. If you just putcompany
only the label will be exported. - If you don’t specify anything in
_fields
, all fields will be included, except related ones. - System fields (
id
,label
andversion
) aren’t included.
Request
PUT /data/{entityName}/export
> Content-Type: application/json
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
no |
This flag modifies how headers are generated. If it is set to |
|
|
no |
These are the query parameters. See Query language for more information. |
Response
A reference to the job in charge of perform the import. To actually fetch the file you need to check when the job is finished and look into the results of the job, where you’ll find something like this:
{
...
"hasErrors": false,
"results": {
"fileLink": "https://docs.slingrs.io/dev/runtime/api/files/588f864eb45fc9000bc1bd5c",
"fileId": "588f864eb45fc9000bc1bd5c",
"recordsExported": 283
},
"status": "FINISHED"
}
The field results.fileLink
contains the URL to download the file. You need to pass the token in the headers
when fetching the file or the token needs to be set in cookies.
PUT /data/{entityName}/export
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f8357b45fc9000bc1bd2a",
"jobId": "588f8357b45fc9000bc1bd2a"
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If you are trying to export more than 1,000,000 records or if query is invalid. |
|
|
You don’t have permissions to export records on this entity. |
|
|
The entity name does not exist. |
Samples
exports companies with type 'b', with a maxium of 50 records
PUT /data/companies/export?type=b&_size=50
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/export?type=b&_size=50
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f3e65b45fc9000bc1baa7",
"jobId": "588f3e65b45fc9000bc1baa7"
}
exports companies with type 'b', with a maxium of 50 records but only the fields name, address->state and mainContact->email.
PUT /data/companies/export?type=b&_size=50&_fields=name,address.state,mainContact.email
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /data/companies/export?type=b&_size=50&_fields=name,address.state,mainContact.email
< Content-Type: application/json
{
"jobLink": "/api/status/jobs/588f3e65b45fc9000bc1baa8",
"jobId": "588f3e65b45fc9000bc1baa8"
}
History
History for one record
GET /data/{entityName}/{id}/history
Returns the history of a record. The entity needs to have history logs enabled.
Request
GET /data/{entityName}/{id}/history
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the record belongs to. |
|
|
yes |
The ID of the record to get its history. |
|
|
no |
|
The number of history records to fetch. Always the latests logs will be retrieved. |
|
no |
Specifies an ID of a history log to start fetching logs from. This is to allow pagination. |
Response
The list of history logs for that record, sorted from the newest to the oldest ones.
GET /data/{entityName}/{id}/history
< Content-Type: application/json
{
"total": 2,
"offset": "588f8b99b45fc9000bc1bfc5",
"items": [
{
"id": "588f8ba7b45fc9000bc1bfce",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802407010,
"ip": "::ffff:10.240.0.15",
"eventType": "USER_RECORD_CHANGED",
"eventCategory": "USER",
"contextPath": "entities.companies.update",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {
"type": {
"json": "a",
"text": "{type:a}"
},
"addresses": {
"json": null,
"text": "{}"
}
},
"newRecord": {
"type": {
"json": "b",
"text": "{type:b}"
},
"addresses": {
"json": null,
"text": "{}"
}
}
},
{
"id": "588f8b99b45fc9000bc1bfc5",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802393836,
"ip": "::ffff:10.240.0.11",
"eventType": "USER_RECORD_CREATED",
"eventCategory": "USER",
"contextPath": "entities.companies.create",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {},
"newRecord": {
"name": "test1",
"state": "active",
"type": "a",
"numberOfEmployees": null,
"isCustomer": false,
"contactInformation": {
"phoneNumber": null,
"email": null,
"id": "588f8b99b45fc9000bc1bfc3",
"label": "Contact Information"
},
"homepage": null,
"taxId": null,
"rating": null,
"notes": null,
"lastMeeting": null,
"lastUpdate": 1485802380000
}
}
]
}
Path | Description |
---|---|
|
The total number of history logs for the record. |
|
The ID of the latest history log, which needs to be sent in the |
|
The history logs. Most of the fields are self explanatory. Next we will describe a few ones. |
|
The category of the event. These are the possible values:
|
|
The type of event, which depends on the category. These are the options:
|
|
This is a path that describe where the change was done. For example if it was a script it will say which script made the change. |
|
Indicates if the record has been deleted or not. |
|
Date when the record was deleted. |
|
Contains the old values of the fields that were modified. On each field it will contain the JSON format as well as a more human-redable format. |
|
Contains the new values of the fields that were modified. On each field it will contain the JSON format as well as a more human-redable format. |
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If record ID is invalid. |
|
|
You don’t have permissions to see history of records for the entity. |
|
|
The entity name does not exist. Keep in mind that this method won’t return this error if the record ID does not exists because you could be asking for a deleted record. |
Samples
gets the history of a company record
GET /data/companies/588f8b99b45fc9000bc1bfc4/history
> Accept: application/json
> token: token
GET /data/companies/588f8b99b45fc9000bc1bfc4/history
< Content-Type: application/json
{
"total": 2,
"offset": "588f8b99b45fc9000bc1bfc5",
"items": [
{
"id": "588f8ba7b45fc9000bc1bfce",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802407010,
"ip": "::ffff:10.240.0.15",
"eventType": "USER_RECORD_CHANGED",
"eventCategory": "USER",
"contextPath": "entities.companies.update",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {
"type": {
"json": "a",
"text": "{type:a}"
},
"addresses": {
"json": null,
"text": "{}"
}
},
"newRecord": {
"type": {
"json": "b",
"text": "{type:b}"
},
"addresses": {
"json": null,
"text": "{}"
}
}
},
{
"id": "588f8b99b45fc9000bc1bfc5",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802393836,
"ip": "::ffff:10.240.0.11",
"eventType": "USER_RECORD_CREATED",
"eventCategory": "USER",
"contextPath": "entities.companies.create",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {},
"newRecord": {
"name": "test1",
"state": "active",
"type": "a",
"numberOfEmployees": null,
"isCustomer": false,
"contactInformation": {
"phoneNumber": null,
"email": null,
"id": "588f8b99b45fc9000bc1bfc3",
"nestedFieldLabel": "Contact Information",
"id": "588f8b99b45fc9000bc1bfc3",
"label": "Contact Information"
},
"homepage": null,
"taxId": null,
"rating": null,
"notes": null,
"lastMeeting": null,
"lastUpdate": 1485802380000
}
}
]
}
History in entity
GET /data/{entityName}/history
Returns the history logs for all records in an entity, which needs to have history logs enabled.
Request
GET /data/{entityName}/history
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
Name of the entity the fetch history logs. |
|
|
no |
Allows to filter by some specific type of events. You can select many separating them by commas. Possible values are:
|
|
|
no |
Allows to filter logs by timestamp. This is the maximum date and you should pass the number of milliseconds since Epoch. |
|
|
no |
Allows to filter logs by timestamp. This is the minimum date and you should pass the number of milliseconds since Epoch. |
|
|
no |
|
The number of history records to fetch. Always the latests logs will be retrieved. |
|
no |
Specifies an ID of a history log to start fetching logs from. This is to allow pagination. |
Response
The list of history logs, sorted from the newest to the oldest ones.
GET /data/{entityName}/history
< Content-Type: application/json
{
"total": 3,
"offset": "588f8ba7b45fc9000bc1bfce",
"items": [
{
"id": "588f9757b45fc9000bc1bfe1",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f9757b45fc9000bc1bfe0",
"recordName": "test2",
"user": "dgaviola@slingr.io",
"timestamp": 1485805399966,
"ip": "::ffff:10.240.0.11",
"eventType": "USER_RECORD_CREATED",
"eventCategory": "USER",
"contextPath": "entities.companies.create",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {},
"newRecord": {
"name": "test2",
"state": "active",
"type": "c",
"color": "#e1e1e1",
"numberOfEmployees": null,
"isCustomer": false,
"contactInformation": {
"phoneNumber": null,
"email": null,
"id": "588f9757b45fc9000bc1bfdf",
"nestedFieldLabel": "Contact Information",
"id": "588f9757b45fc9000bc1bfdf",
"label": "Contact Information"
},
"homepage": null,
"taxId": null,
"rating": null,
"notes": null,
"lastMeeting": null,
"lastUpdate": 1485805380000
}
},
{
"id": "588f8ba7b45fc9000bc1bfce",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802407010,
"ip": "::ffff:10.240.0.15",
"eventType": "USER_RECORD_CHANGED",
"eventCategory": "USER",
"contextPath": "entities.companies.update",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {
"type": {
"json": "a",
"text": "{type:a}"
},
"addresses": {
"json": null,
"text": "{}"
}
},
"newRecord": {
"type": {
"json": "b",
"text": "{type:b}"
},
"addresses": {
"json": null,
"text": "{}"
}
}
}
]
}
Path | Description |
---|---|
|
The total number of history logs matched by the query. |
|
The ID of the latest history log, which needs to be sent in the |
|
The history logs. Please check the documentation for History for one record. |
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If the query is invalid. |
|
|
You don’t have permissions to see history of records for the entity. |
|
|
The entity name does not exist. |
Samples
gets the last two history logs in entity 'companies'
GET /data/companies/history?_size=2
> Accept: application/json
> token: token
GET /data/companies/history?_size=2
< Content-Type: application/json
{
"total": 3,
"offset": "588f8ba7b45fc9000bc1bfce",
"items": [
{
"id": "588f9757b45fc9000bc1bfe1",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f9757b45fc9000bc1bfe0",
"recordName": "test2",
"user": "dgaviola@slingr.io",
"timestamp": 1485805399966,
"ip": "::ffff:10.240.0.11",
"eventType": "USER_RECORD_CREATED",
"eventCategory": "USER",
"contextPath": "entities.companies.create",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {},
"newRecord": {
"name": "test2",
"state": "active",
"type": "c",
"color": "#e1e1e1",
"numberOfEmployees": null,
"isCustomer": false,
"contactInformation": {
"phoneNumber": null,
"email": null,
"id": "588f9757b45fc9000bc1bfdf",
"nestedFieldLabel": "Contact Information",
"id": "588f9757b45fc9000bc1bfdf",
"label": "Contact Information"
},
"homepage": null,
"taxId": null,
"rating": null,
"notes": null,
"lastMeeting": null,
"lastUpdate": 1485805380000
}
},
{
"id": "588f8ba7b45fc9000bc1bfce",
"entityId": "57fce228e4b0f6600fdfb836",
"entityName": "companies",
"entityVersion": 57,
"recordId": "588f8b99b45fc9000bc1bfc4",
"recordName": "test1",
"user": "dgaviola@slingr.io",
"timestamp": 1485802407010,
"ip": "::ffff:10.240.0.15",
"eventType": "USER_RECORD_CHANGED",
"eventCategory": "USER",
"contextPath": "entities.companies.update",
"recordDeleted": null,
"deletionDate": null,
"oldRecord": {
"type": {
"json": "a",
"text": "{type:a}"
},
"addresses": {
"json": null,
"text": "{}"
}
},
"newRecord": {
"type": {
"json": "b",
"text": "{type:b}"
},
"addresses": {
"json": null,
"text": "{}"
}
}
}
]
}
Files handling
Slingr apps can store any kind of files than later can be downloaded, shared or referenced by fields in records.
If you need to reference a file in a record from a file field, you will usually upload the file first and then, once you have the ID of the file, you can set it as the the value of the file field.
If a file isn’t referenced by any record, it will be deleted after a few hours. This means you shouldn’t upload files here if you won’t reference them from records in your app.
Uploading files
POST /files
Uploads a file to the app. It will be stored temporarily until it gets referenced by a record. If no record references the file in 12 hours, the file will be removed.
Request
The file needs to be uploaded as a multi-part. You can upload any type of file.
POST /files
> Content-Type: multipart/form-data
> Accept: application/json
> token: token
Response
The metadata of the uploaded file.
POST /files
< Content-Type: application/json
{
"fileId": "588f9f1eb45fc9000bc1c010",
"fileLink": "/files/588f9f1eb45fc9000bc1c010"
}
Path | Description |
---|---|
|
The ID of the file. You can use this ID to reference the file from file fields in records. |
Samples
uploads a file
POST /files
> Content-Type: multipart/form-data
> Accept: application/json
> token: token
test file in multi-part
POST /files
< Content-Type: application/json
{
"fileId": "588f9f1eb45fc9000bc1c010",
"fileLink": "/files/588f9f1eb45fc9000bc1c010"
}
Downloading files
GET /files/{id}
Downloads a file. This service is only available for developer and system users.
Request
GET /files/{id}
> token:
> : token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
The ID of the file to download. |
Response
Returns the file to download.
GET /files/{id}
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
the content of the file
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
The file doesn’t exist. |
Samples
fetches a file
GET /files/588f9f1eb45fc9000bc1c010
> token:
> : token
GET /files/588f9f1eb45fc9000bc1c010
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
this is the content of the file
Downloading record files
GET /data/{entityName}/{recordId}/files/{fileId}
Downloads a file that belongs to a specific record. User permissions check is performed.
Request
GET /data/{entityName}/{recordId}/files/{fileId}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
ID of the record to fetch file. |
|
|
yes |
ID of the file to be retrieved. |
Response
Returns the record file to download.
GET /data/{entityName}/{recordId}/files/{fileId}
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
the content of the file
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
The entity or record or file can no be found. |
|
|
Provided token does not have permissions to access specified file. |
Samples
fetches a file that belongs to a record
GET /data/companies/57fd2d65e4b0ce322b0c8665/files/588fa383b45fc9000bc1c014
> Accept: application/json
> token: token
GET /data/companies/57fd2d65e4b0ce322b0c8665/files/588fa383b45fc9000bc1c014
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
this is the content of the file
Sharing files
PUT /files/{id}/share
Shares a file through a public link. The link will be valid for an hour.
Request
PUT /files/{id}/share
> Content-Type: application/json
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
no |
|
Time to expire in milliseconds. |
Response
The public link to download the file. This link won’t require any permission.
PUT /files/{id}/share
< Content-Type: application/json
{
"sharedFileId": "588fa383b45fc9000bc1c014",
"sharedFileLink": "/files/shared/588fa383b45fc9000bc1c014"
}
Path | Description |
---|---|
|
This is the ID of the shared file. |
|
The link to download the file. You should prepend the API endpoint. |
Samples
shares a file which will expire in one minute
PUT /files/588f9f1eb45fc9000bc1c010/share?ttl=60000
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /files/588f9f1eb45fc9000bc1c010/share?ttl=60000
< Content-Type: application/json
{
"sharedFileId": "588fa383b45fc9000bc1c014",
"sharedFileLink": "/files/shared/588fa383b45fc9000bc1c014"
}
Fetch shared file
GET /files/shared/{id}
Downloads a shared file.
Request
GET /files/shared/{id}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
The ID of the shared file to download. |
Response
Returns the shared file to download.
GET /files/shared/{id}
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
the content of the file
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
The shared file doesn’t exist. |
Samples
fetches a shared file
GET /files/shared/588fa383b45fc9000bc1c014
> Accept: application/json
> token: token
GET /files/shared/588fa383b45fc9000bc1c014
> Content-Type: application/force-download
> Content-Disposition: attachment; filename=file.ext
this is the content of the file
Monitoring and troubleshooting
Logs
Logs allow to know what’s going on in the app. The structure of a log is this one:
{
"id": "57fce0bfe4b0f6600fdfb82c",
"type": "APP",
"subType": null,
"level": "INFO",
"message": "PUT /api/metadata/clearCache",
"userEmail": "system@docs.slingrs.io",
"adminUserEmail": null,
"timestamp": 1476190399791,
"ip": "10.64.2.3",
"additionalInfo": {}
}
Path | Description |
---|---|
|
ID of the log. |
|
Indicates the type of log. Possible options are:
|
|
Based on the
|
|
Level of the log. It could be |
|
The message of the log. |
|
The email of the current user when the log was generated. It could be the system user. |
|
If the user is being impersonated, this is the email of the admin user. |
|
Timestamp when the log was generated. It is in milliseconds since Epoch. |
|
|
|
This fields might provide additional info that could be useful when there are issues. Do not use this information to automate any process because it could change without notice. |
Get logs
GET /status/logs
Query logs from the app.
Keep in mind that logs rotate and when the maximum size of logs is reached older ones are lost.
Request
GET /status/logs
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
no |
Allows to filter by user email doing a partial match. |
|
|
no |
Allows to filter by a span of time. For example you can send If this parameter is specified, parameters |
|
|
no |
The minimum timestamp in milliseconds since Epoch. |
|
|
no |
The maximum timestamp in milliseconds since Epoch. |
|
|
no |
The level of logs to find. You can specify many levels separated by commas. |
|
|
no |
Allows to filter by the message in the logs. It will do a partial search. |
|
|
no |
|
The maximum number of logs to retrieve. |
|
no |
This is the offset to start getting logs. When you make a query you will get the offset you need to use to get more logs. |
Response
A list of logs in JSON format.
GET /status/logs
< Content-Type: application/json
{
"total": 151
"items": [
{
"id": "58907c10b45fc9000bc1c020",
"type": "APP",
"subType": "LOGIN",
"level": "INFO",
"message": "POST /login",
"userEmail": "dgaviola@slingr.io",
"adminUserEmail": null,
"timestamp": 1485863952895,
"ip": null
},
{
"id": "58907c1bb45fc9000bc1c023",
"type": "APP",
"subType": null,
"level": "INFO",
"message": "GET /api/users/57fce0c3e4b0ce322b0c06b2?appsVersion=true",
"userEmail": "dgaviola@slingr.io",
"adminUserEmail": null,
"timestamp": 1485863963701,
"ip": "::ffff:10.240.0.11"
},
{
"id": "589085b0b45fc9000bc1c02f",
"type": "APP",
"subType": null,
"level": "INFO",
"message": "Validation exceptions on record [test]. Error: [file: Content type is required when uploading a file and must be a string]",
"userEmail": "dgaviola@slingr.io",
"adminUserEmail": null,
"timestamp": 1485866416124,
"ip": null,
"additionalInfo": {
"recordLabel": "test",
"errors": [
{
"code": "INVALID",
"field": "file",
"message": "Content type is required when uploading a file and must be a string"
}
]
}
},
{
"id": "589085bdb45fc9000bc1c030",
"type": "APP",
"subType": "REST_API_RECORD_UPDATED",
"level": "INFO",
"message": "PUT /api/data/files/585aea800d29d300072484a8",
"userEmail": "dgaviola@slingr.io",
"adminUserEmail": null,
"timestamp": 1485866429630,
"ip": "::ffff:10.240.0.15"
},
{
"id": "589085bfb45fc9000bc1c032",
"type": "APP",
"subType": null,
"level": "INFO",
"message": "Data record of type [files] with label [test] was changed successfully",
"userEmail": "dgaviola@slingr.io",
"adminUserEmail": null,
"timestamp": 1485866431823,
"ip": null
},
]
}
Path | Description |
---|---|
|
The total number of logs matched by the query. |
|
The offset to use to get more logs. |
|
The logs found. Please check the docs for Logs for more information. |
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If you try to query logs with a user who is not a developer. |
Samples
finds two logs for yesterday for one specific user
GET /status/logs?period=yesterday&userEmail=test@slingr.io&_size=2
> Accept: application/json
> token: token
GET /status/logs?period=yesterday&userEmail=test@slingr.io&_size=2
< Content-Type: application/json
{
"items": [
{
"id": "58907c10b45fc9000bc1c020",
"type": "APP",
"subType": "LOGIN",
"level": "INFO",
"message": "POST /login",
"userEmail": "test@slingr.io",
"adminUserEmail": null,
"timestamp": 1485863952895,
"ip": null
},
{
"id": "58907c19b45fc9000bc1c021",
"type": "APP",
"subType": null,
"level": "INFO",
"message": "GET /api/users/current",
"userEmail": "test@slingr.io",
"adminUserEmail": null,
"timestamp": 1485863961326,
"ip": "::ffff:10.240.0.16"
}
],
"total": 151
}
Post logs
POST /status/logs
Creates a log. You only need to send the message and the level of log. Other fields will be calculated
automatically. An optional additionalInfo
object can be send to add extra fields.
Request
POST /status/logs
> Content-Type: application/json
> Accept: application/json
> token: token
{
"level": "INFO",
"message": "This is a test log",
"additionalInfo": {
"test": "Additional info property"
}
}
Response
The created log in JSON format.
POST /status/logs
< Content-Type: application/json
{
"id": "589085bdb45fc9000bc1c030",
"type": "EXTERNAL",
"subType": null,
"level": "INFO",
"message": "This is a test log",
"userEmail": "test@slingr.io",
"adminUserEmail": null,
"timestamp": 1485866429630,
"ip": null,
"additionalInfo": {
"test": "Additional info property"
}
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If there are validation errors. When this happens you will get the details of the errors in the body:
|
|
|
If you try to create a log with a user who is not a developer. |
Samples
creates a new log
POST /status/logs
> Content-Type: application/json
> Accept: application/json
> token: token
{
"level": "INFO",
"message": "This is a test log",
"additionalInfo": {
"test": "Additional info property"
}
}
POST /status/logs
< Content-Type: application/json
{
"id": "589085bdb45fc9000bc1c030",
"type": "EXTERNAL",
"subType": null,
"level": "INFO",
"message": "This is a test log",
"userEmail": "test@slingr.io",
"adminUserEmail": null,
"timestamp": 1485866429630,
"ip": "::ffff:10.240.0.15",
"additionalInfo": {
"test": "Additional info property"
}
}
Jobs
With the API for jobs it is possible to check status, progress, logs, as well as some additional information to get a good understanding of what’s going on with the of a job.
This is the general structure of a job:
{
"id": "588a02c13b063a0007605032",
"label": "Executing action countEmployees on entity companies",
"type": "EXECUTE_ACTION",
"runBy": {
"id": "57fce0c3e4b0ce322b0c06b2",
"fullName": "Diego Gaviola"
},
"parentJob": null,
"rootJob": null,
"createDate": 1485439681643,
"startDate": 1485439681652,
"endDate": 1485439681807,
"status": "FINISHED",
"hasErrors": false,
"progress": 100,
"recordsCount": 0,
"recordsProcessed": 0,
"childrenJobsCount": 0,
"childrenJobsProcessed": 0,
"stoppable": true,
"lowPriority": false,
"data": {}
"results": {}
}
Path | Description | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
ID of the job. |
||||||||||||||||||||||||||||||||||||||||||||
|
Name of the jobs. It is a simple description of what the job does. This description might change without notice so don’t use it to take decisions in your code. |
||||||||||||||||||||||||||||||||||||||||||||
|
This is the type of job. There are many types of jobs, however some of them might change without notice. The only job types we support are the following ones:
Other jobs are system ones and you shouldn’t base your code on any of them as we might change or remove them. |
||||||||||||||||||||||||||||||||||||||||||||
|
It is a map with |
||||||||||||||||||||||||||||||||||||||||||||
|
It is a map with The parent job is the job that was being executed when the job was created. If the job was not created during
the execution of another job, then this field will be |
||||||||||||||||||||||||||||||||||||||||||||
|
It is a map with A root job is one that doesn’t have a parent. If this field is |
||||||||||||||||||||||||||||||||||||||||||||
|
The date the job was created in milliseconds. |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
The date when the execution of the job finished. This can be |
||||||||||||||||||||||||||||||||||||||||||||
|
Current status of the job. It could be:
|
||||||||||||||||||||||||||||||||||||||||||||
|
If |
||||||||||||||||||||||||||||||||||||||||||||
|
This is a number from 0 to 100 that indicates the progress of the job. Keep in mind that some jobs will move directly from 0 to 100 as there is no progress information. Also in cases were progress is updated it might not be consistent, so use it carefully. |
||||||||||||||||||||||||||||||||||||||||||||
|
If the job needs to do something with records, this number will indicate the number of records involved. |
||||||||||||||||||||||||||||||||||||||||||||
|
If the job needs to do something with records, this number will indicate the number of records that have been processed already. |
||||||||||||||||||||||||||||||||||||||||||||
|
If other jobs were created during the execution of the job, this counter will increase to show how many children jobs have been created. This number will be 0 at the beginning but could grow over time, so it isn’t fixed. |
||||||||||||||||||||||||||||||||||||||||||||
|
The number of children jobs that are finished. |
||||||||||||||||||||||||||||||||||||||||||||
|
If |
||||||||||||||||||||||||||||||||||||||||||||
|
If |
||||||||||||||||||||||||||||||||||||||||||||
|
The content of this field depends on the job. Here you will find more information about parameters for the job. Start app
Import records
Export records
Delete records
Execute action
Execute listener
Import users
Deploy endpoint
Undeploy endpoint
|
||||||||||||||||||||||||||||||||||||||||||||
|
The content of this field depends on the job. Here you will find information about the results of executing the job. Import records
Export records
Delete records The result will be a map like this one:
One important thing to keep in mind is that the maximum number of responses in this map will be 1,000. If you execute the delete process over more than 1,000 records you might not be able to collect the response for each one. Execute action The results of this job depends on the type of action. If the action is of type
One important thing to keep in mind is that the maximum number of responses in this map will be 1,000. If you execute the action over more than 1,000 records you might not be able to collect the response for each one. If the action is of type
Import users
Export users
|
Get one job
GET /status/jobs/{id}
Gets one job by ID.
Request
GET /status/jobs/{id}
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
yes |
The ID of the job. |
Response
The job in JSON format.
GET /status/jobs/{id}
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
"label": "Execute action countEmployees from entity companies",
"type": "EXECUTE_ACTION",
"runBy": {
"id": "57fce0c3e4b0ce322b0c06b2",
"fullName": "Diego Gaviola"
},
"parentJob": null,
"rootJob": null,
"createDate": 1485439681643,
"startDate": 1485439681652,
"endDate": 1485439681807,
"status": "FINISHED",
"hasErrors": false,
"progress": 100,
"recordsCount": 0,
"recordsProcessed": 0,
"childrenJobsCount": 0,
"childrenJobsProcessed": 0,
"stoppable": true,
"lowPriority": false
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
The job doesn’t exist |
Samples
gets a job by ID
GET /status/jobs/588a02c13b063a0007605032
> Accept: application/json
> token: token
GET /status/jobs/588a02c13b063a0007605032
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
"label": "Execute action countEmployees from entity companies",
"type": "EXECUTE_ACTION",
"runBy": {
"id": "57fce0c3e4b0ce322b0c06b2",
"fullName": "Diego Gaviola"
},
"parentJob": null,
"rootJob": null,
"createDate": 1485439681643,
"startDate": 1485439681652,
"endDate": 1485439681807,
"status": "FINISHED",
"hasErrors": false,
"progress": 100,
"recordsCount": 0,
"recordsProcessed": 0,
"childrenJobsCount": 0,
"childrenJobsProcessed": 0,
"stoppable": true,
"lowPriority": false
}
List jobs
GET /status/jobs
Lists jobs in the app.
Request
GET /status/jobs
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
no |
The type of job. Possible values are: You can specify many separated by commas. |
|
|
no |
The status of the job. Possible values are: You can specify many separated by commas. |
|
|
no |
Allows to filter jobs if they have errors. |
|
|
no |
Allows to filter jobs by start date. This is the initial range limit to filter from, it can be used alone or in combination with startTo. |
|
|
no |
Allows to filter jobs by start date. This is the final range limit to filter to, it can be used alone or in combination with startFrom. |
|
|
no |
Allows to filter jobs by end date. This is the initial range limit to filter from, it can be used alone or in combination with endTo. |
|
|
no |
Allows to filter jobs by end date. This is the final range limit to filter to, it can be used alone or in combination with endFrom. |
|
|
no |
Allows to filter jobs by creation date. This is the initial range limit to filter from, it can be used alone or in combination with createTo. |
|
|
no |
Allows to filter jobs by creation date. This is the final range limit to filter to, it can be used alone or in combination with createFrom. |
|
|
no |
|
The maximum number of jobs to retrieve. |
|
no |
This is the offset to start getting jobs. When you make a query you will get the offset you need to use to get more jobs. |
Response
A list of jobs in JSON format.
GET /status/jobs
< Content-Type: application/json
{
"total": 54,
"offset": "5890d8ddb45fc9000bc1c2cf",
"items": [
{
"id": "5890d8deb45fc9000bc1c2d3",
...
},
{
"id": "5890d8deb45fc9000bc1c2d1",
...
},
{
"id": "5890d8ddb45fc9000bc1c2cf",
...
]
}
Path | Description |
---|---|
|
The total number of jobs matched by the query. |
|
The offset to use to get more jobs. |
|
The jobs found. Please check the docs for Jobs for more information. |
Samples
finds up to three finished jobs
GET /status/jobs?status=FINISHED&_size=3
> Accept: application/json
> token: token
GET /status/jobs?status=FINISHED&_size=3
< Content-Type: application/json
{
"total": 50,
"offset": "5890d8ddb45fc9000bc1c2cf",
"items": [
{
"id": "5890d8deb45fc9000bc1c2d3",
...
},
{
"id": "5890d8deb45fc9000bc1c2d1",
...
},
{
"id": "5890d8ddb45fc9000bc1c2cf",
...
]
}
Get logs of a job
GET /status/jobs/{id}/logs
Query logs from a job.
Request
GET /status/jobs/{id}/logs
> Accept: application/json
> token: token
Parameter | Required | Default | Description |
---|---|---|---|
|
no |
Allows to filter by a span of time. For example you can send If this parameter is specified, parameters |
|
|
no |
The minimum timestamp in milliseconds since Epoch. |
|
|
no |
The maximum timestamp in milliseconds since Epoch. |
|
|
no |
The level of logs to find. You can specify many levels separated by commas. Possible values are |
|
|
no |
Allows to filter by the message in the logs. It will do a partial search. |
|
|
no |
|
The maximum number of users to retrieve. |
|
no |
This is the offset to start getting users. When you make a query you will get the offset you need to use to get more users. |
Response
A list of logs in JSON format.
GET /status/jobs/{id}/logs
< Content-Type: application/json
{
"total": 3,
"items": [
{
"timestamp": 1485887710544,
"level": "INFO",
"message": "Starting processing"
},
{
"timestamp": 1485887710546,
"level": "INFO",
"message": "Cleaning up"
},
{
"timestamp": 1485887710704,
"level": "INFO",
"message": "Process completed"
}
]
}
Path | Description |
---|---|
|
The total number of logs matched by the query. |
|
The offset to use to get more logs. |
|
The logs found that contains three fields:
|
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If the job is not found. |
Samples
finds logs for one job
GET /status/job/5890d8deb45fc9000bc1c2d3/logs
> Accept: application/json
> token: token
GET /status/job/5890d8deb45fc9000bc1c2d3/logs
< Content-Type: application/json
{
"total": 3,
"items": [
{
"timestamp": 1485887710544,
"level": "INFO",
"message": "Starting processing"
},
{
"timestamp": 1485887710546,
"level": "INFO",
"message": "Cleaning up"
},
{
"timestamp": 1485887710704,
"level": "INFO",
"message": "Process completed"
}
]
}
Stop job
PUT /status/jobs/{id}/stop
Stops a job. If the job was running it might need some time to stop gracefully. During that time the
status will be STOPPING
. Once the job has been stopped gracefully the status will change to STOPPED
.
Jobs that are stopped can be resumed.
Request
PUT /status/jobs/{id}/stop
> Content-Type: application/json
> Accept: application/json
> token: token
Response
The job in JSON format.
PUT /status/jobs/{id}/stop
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "STOPPING",
...
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If job cannot be stopped. It could be because jobs of this type cannot be stopped or this is not a root job. |
|
|
You don’t have permissions to stop this job. If you are not a developer you can only stop jobs you ran. |
|
|
If job is not found. |
Samples
stops a job
PUT /status/jobs/588a02c13b063a0007605032/stop
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /status/jobs/588a02c13b063a0007605032/stop
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "STOPPING",
...
}
Force to stop job
PUT /status/jobs/{id}/forceStop
When stopping a job it will try to do it gracefully. If the job keeps running and you need to stop it, you can force it, what will kill the job immediately.
Keep in mind that the processing the job was doing might be interrupted and data might be in a bad state when doing this, so use it only for very special cases.
Request
PUT /status/jobs/{id}/forceStop
> Content-Type: application/json
> Accept: application/json
> token: token
Response
The job in JSON format.
PUT /status/jobs/{id}/forceStop
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "STOPPED",
...
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If job cannot be stopped. It could be because jobs of this type cannot be stopped, this is not a root
job or because the status is different from |
|
|
You don’t have permissions to stop this job. If you are not a developer you can only stop jobs you ran. |
|
|
If job is not found. |
Samples
force to stop a job
PUT /status/jobs/588a02c13b063a0007605032/forceStop
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /status/jobs/588a02c13b063a0007605032/forceStop
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "STOPPED",
...
}
Cancel job
PUT /status/jobs/{id}/cancel
Cancels a job. Only jobs that are in STOPPED
can be canceled.
Jobs that are canceled cannot be resumed.
Request
PUT /status/jobs/{id}/cancel
> Content-Type: application/json
> Accept: application/json
> token: token
Response
The job in JSON format.
PUT /status/jobs/{id}/cancel
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "CANCELED",
...
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If job cannot be canceled. It could be because the job is in a bad status or it is not a root job. |
|
|
You don’t have permissions to cancel this job. If you are not a developer you can only cancel jobs you ran. |
|
|
If job is not found. |
Samples
cancels a job
PUT /status/jobs/588a02c13b063a0007605032/cancel
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /status/jobs/588a02c13b063a0007605032/cancel
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "CANCELED",
...
}
Resume job
PUT /status/jobs/{id}/resume
Resumes a job that is stopped. The job will continue execution where it left. If the job was not started
when it was stopped, the status will be set to PENDING
instead of RUNNING
.
Request
PUT /status/jobs/{id}/resume
> Content-Type: application/json
> Accept: application/json
> token: token
Response
The job in JSON format.
PUT /status/jobs/{id}/resume
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "RUNNING",
...
}
Possible errors
Error code | HTTP Status Code | Description |
---|---|---|
|
|
If job cannot be resumed. It could be because the job is in a bad status or it is not a root job. |
|
|
You don’t have permissions to resume this job. If you are not a developer you can only resume jobs you ran. |
|
|
If job is not found. |
Samples
resumes a job
PUT /status/jobs/588a02c13b063a0007605032/resume
> Content-Type: application/json
> Accept: application/json
> token: token
PUT /status/jobs/588a02c13b063a0007605032/resume
< Content-Type: application/json
{
"id": "588a02c13b063a0007605032",
...
"status": "RUNNING",
...
}