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 or updatedId: the internal ID of the record
    • externalId: the external ID of the record
    • uuid: 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 failed
    • record: 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

  1. 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"
            }
        ]
    }
    
  2. 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"
            }
        ]
    }
    
  3. 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"
            }
        ]
    }
    
  4. 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://\""
            }
        ]
    }
    
  5. Resource specific

    1. 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\"}} }"
              }
          ]
      }
      
    2. 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\" }"
              }
          ]
      }
      
    3. 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\": \"\" }"
              }
          ]
      }