HTTP Responses
Primary things to note about server responses to Bulk API PUT and POST methods:
Server responses are in JSON format, not NDJSON, which is required for request payloads.
A server response to a Bulk API call refers semantically to the entire request, not to the individual create/update operations included in the request. This means that, unless there was an internal error during processing, a bulk request will return
200 OK
.Requests will timeout after approximately 1 minute and may result in unexpected behaviour. To avoid timeouts, limit the size of requests to approximately 500 records per request - see Frequently Asked Questions for further guidance on best practice sizing and batching of requests.
Response bodies contain a list of all successfully created records with the following information:
jobId
: which record this is referring to (1-indexed line number from the request body)createdId
orupdatedId
: the internal ID of the recordexternalId
: the external ID of the recorduuid
: the universally unique identifier of the record *
*NOTE
uuid
information is currently only returned from customer record types.Response bodies also contain a list of all errors that were encountered with the following information:
jobId
: which record this is referring to (1-indexed line number from the request body)message
: an error message describing why this record failedrecord
: a copy of the line that failed (encoded as a string within the JSON)
The following is a sample server response to a bulk create (POST) request for creating two records; the message indicates that the first record was successfully created and assigned an ID of 90499,
and that the second line’s record failed due to malformed JSON:
{
"newRecords": [
{
"jobId": 1,
"createdId": 90499,
"externalId": "abc123",
"uuid": "123e4567-e89b-12d3-a456-426614174000"
}
],
"errors": [
{
"jobId": 2,
"message": "Could not decode or validate JSON for line number 2: invalid character ',' looking for beginning of value",
"record": "{\"invalidJson\":,}"
}
]
}
How to Address 4xx Errors
4xx errors refer to errors that begin with 4 (e.g. 400, 404, etc). When receiving a 4xx error, this usually means that something is wrong in your request to the Bulk API.
Best practices when receiving a 4xx error:
- Validate the endpoint
- Check the record for invalid data. Fields may have special requirements that your data must abide by
- Validate that your Bearer token is correct. You should receive a 401 Authorization Required message if your Bearer token is invalid or missing
How to Address 5xx Errors
5xx errors refer to errors that begin with 5 (e.g. 500, 501, etc). When receiving a 5xx error, this usually means that a server error occurred while attempting to use the Bulk API.
Best practices when receiving a 5xx error:
- Double check that the request is valid, then try resending it after 15 minutes.
- If the error persists, retries should be made on an exponential backoff interval.
The following formula is suggested:(initial_interval)*2^(#_retries_made)
For instance, if the initial wait interval is 15 minutes, and three retries have occured, the waiting period before attempting the fourth retry could be calculated as follows:Wait_time = 15*(2^3) = 120 minutes
- If the error continues please contact Tulip Support.
Types of validation errors
Records with duplicate external ids being created (only applies to Tulip 7.0+)
eg., POST v1/storeops/stores with payload
{"externalId":"test"}\n{"externalId":"test"}
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not create job number 1: Record with the specified unique keys already exists" } ] }
Missing required field or invalid field
eg., POST v1/storeops/stores with payload
{"externalId":"test"}
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not create job number 1: Invalid field 'country_id' supplied for resource 'store': Store does not have a valid country ID" } ] }
Bad JSON formatting
eg., POST v1/storeops/stores with payload
{"externalId":"test"
<- notice missing } at the end{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not decode or validate JSON for job number 1: unexpected EOF" } ] }
Bad image urls for certain resources (catalog, category, customer, employee, product, variant)
eg., POST v1/catalog/catalogs with payload
{"externalId":"bla", "image":"test"}
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not upload image for job number 1 (URL test) to Imbo: Problem uploading image to Imbo: Could not validate image URL: Image URL \"test\" does not appear valid: no leading \"http://\" or \"https://\"" } ] }
Resource specific
Store hours
eg., POST v1/storeops/stores with payload
{"externalId":"store2", "hours": {"monday": {"open": null, "close":"02:00:00"}} }
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not create line number 0: Invalid field 'hours' supplied for resource 'store': hours must either both be null or neither be null", "record": "{\"externalId\":\"store2\", \"hours\": {\"monday\": {\"open\": null, \"close\":\"02:00:00\"}} }" } ] }
Auth user password length
eg., POST v2/auth/users with payload
{ "disabled": false, "employeeId": 9, "password": "", "roleIds": [ 1, 2 ], "username": "managerxyz" }
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not decode or validate JSON for line number 1: Failed to create Users : Validation error : Password must be between 2 and 64 character long", "record": "{ \"disabled\": false, \"employeeId\": 9, \"password\": \"\", \"roleIds\": [ 1, 2 ], \"username\": \"managerxyz\" }" } ] }
Auth user username length
eg., POST v2/auth/users with payload
{ "disabled": false, "employeeId": 19, "password": "12345", "roleIds": [ 1, 2 ], "username": "" }
{ "newRecords": null, "errors": [ { "jobId": 1, "message": "Could not decode or validate JSON for line number 1: Failed to create Users : Validation error : Username must be at least one character long", "record": "{ \"disabled\": false, \"employeeId\": 19, \"password\": \"12345\", \"roleIds\": [ 1, 2 ], \"username\": \"\" }" } ] }