Skip to content

Send records in batches

POST /api/v1/records/batch sends up to 1,000 records in one request. Each is created or updated exactly as if you had sent it with Send a record. Use it for a first load, for a nightly export, or any time you have more than one record to send.

The body is a JSON array of records, not an object. Each record has the same fields as a single record, and the same limits.

Terminal window
curl -i -X POST https://app.samesake.co.uk/api/v1/records/batch \
-H "X-Api-Key: mk_abcd1234_0123456789abcdefghjkmnpqrstvwxyz" \
-H "Content-Type: application/json" \
-d '[
{
"sourceRecordId": "CRM-10042",
"title": "Ms",
"firstName": "Priya",
"lastName": "Sharma",
"email": "priya.sharma@example.com",
"phones": ["07700 900123"]
},
{
"sourceRecordId": "CRM-10043",
"title": "Mr",
"firstName": "Tom",
"lastName": "Fletcher",
"dateOfBirth": "12/09/1979",
"postcode": "M1 4BT",
"phones": ["07700 900456"]
}
]'

Try it in the API reference

You get 200 OK and an array with one result for each record, in the order you sent them:

Response: 200 OK
[
{ "sourceRecordId": "CRM-10042", "recordId": "rec_7k2m9xq4ht3b", "outcome": "Created" },
{ "sourceRecordId": "CRM-10043", "recordId": "rec_3n8p2w6c9r4d", "outcome": "Updated" }
]

sourceRecordId in a result is the ID as Samesake read it, without spaces at either end. outcome is one of:

Outcome Meaning
Created The source had no record with this ID.
Updated The record’s details changed, or it had been deleted and is now restored.
Unchanged The record already had exactly these details. Nothing was done.

Sending a record that hasn’t changed is harmless, and cheap to do. So a nightly job can send everything, without working out what changed.

Samesake checks every record before it saves any. If one record breaks a limit, the whole batch is refused with 400 Bad Request, nothing is saved, and errors names each problem by the record’s position, counting from 0:

Response: 400 Bad Request
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"[1].email": ["email must be at most 200 characters."],
"[3].sourceRecordId": ["sourceRecordId is required."]
},
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00"
}

Here the second record (position 1) has an email address that’s too long, and the fourth (position 3) has no sourceRecordId. Fix those and send the batch again: it’s safe to repeat, because nothing was saved the first time.

Other refusals:

  • An empty array: errors has records, “At least one record is required.”
  • More than 1,000 records: errors has records, “At most 1000 records are allowed per request.”
  • A null in place of a record: errors names its position, with “Record is required.”
  • A body that isn’t a JSON array of objects, or isn’t JSON: 400 without errors.
  • A body over 8 MB: 413 Payload Too Large. A batch of 1,000 ordinary records is far smaller than that.

To load every record from a system:

  1. Read your records in pages of up to 1,000.
  2. Send each page as a batch, one after another.
  3. Check each response. On 429, wait the number of seconds in Retry-After, then send the same batch again. On 409, send it again. Errors and limits has the full list.

Each key can make 600 requests a minute, and each request can hold 1,000 records, so the rate limit allows far more than you’re likely to send. A first load of 100,000 records is 100 requests.

Send each sourceRecordId once in a batch. If you send the same one twice, the copies are applied in the order you sent them, so the last copy wins, and each copy gets its own result with the same recordId (for a new ID, Created then Updated).

If you have a CSV export and no developer to hand, an admin can upload the file in the app instead. A file can be up to 50 MB.

A batch only creates and updates. It never deletes. To keep Samesake in step with your system, do one of these:

  • Send each change as it happens, and delete records as they’re deleted.
  • If your system can’t tell you what was deleted, send a snapshot from time to time: a complete list, where records missing from it are deleted.