Update up to ten records in one call
const url = 'https://api.sloose.com/orgs/org_9f3c/connectors/cnn_9f2a/records/Accounts';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"runId":"example","automations":"example","items":[{"rowKey":"example","recordId":"example","payload":{"additionalProperty":"example"},"phase":"patch","target":"Parent_Account","keys":[["Account_Number","ac-1"]]}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api.sloose.com/orgs/org_9f3c/connectors/cnn_9f2a/records/Accounts \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "runId": "example", "automations": "example", "items": [ { "rowKey": "example", "recordId": "example", "payload": { "additionalProperty": "example" }, "phase": "patch", "target": "Parent_Account", "keys": [ [ "Account_Number", "ac-1" ] ] } ] }'Updates 1 to 10 existing records in ONE call under an authorised run — for Zoho, one API credit where one record a call spends one each (P0, #1741). Each update is metered as a single update meters it: admitted before the write, in order, a row on its first record; at the run’s ceiling the batch admits what fits and the rest are not sent (RUN_STOPPED). An update of the record a row already made in this module costs nothing more; naming a different record under the same row key and module is refused per update (ROW_KEY_REUSED). A row key, phase and field may appear once a request (ROW_KEY_REPEATED), and a record once (RECORD_REPEATED). The answer is one result per update, in the order sent: ok, or Zoho’s word for it relayed as a single update relays it — a refusal released, or an update Zoho said nothing about (zoho.unanswered), which stays counted and may have been applied. A failure of the whole call is every update’s. Every attempt is recorded in the run’s records under the number the ledger gave it. The destination’s own automations do not run unless the write asks for them: send automations: true to ask for them on this write; absent or false asks for none, whatever they would otherwise do on a create or an update. For a Zoho CRM that means its workflow rules, and no other kind of automation, a cadence for one, is decided by this field (#1816).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The organisation id the session was issued for. A token for one organisation can never read another.
Example
org_9f3cThe organisation id the session was issued for. A token for one organisation can never read another.
The connector id, from GET /orgs/{org}/connectors.
Example
cnn_9f2aThe connector id, from GET /orgs/{org}/connectors.
The module’s API name in the destination.
Example
AccountsThe module’s API name in the destination.
Request Bodyrequired
Section titled “Request Bodyrequired”object
The run from POST /entitlements/runs/authorise. Required.
Run the destination’s own automations on this write: the import’s own switch (#1816), a boolean where only true asks, and absent, false or any other value is read as off. What it means is the destination’s: for a Zoho CRM, true asks it to run its workflow rules (trigger: ['workflow']) and off sends trigger: [], as Zoho’s own import does; Sloose does not ask Zoho to run approvals or blueprints, and a cadence, which Zoho decides on another switch, is not decided by this field.
One to 10 updates, written in this order.
object
The row this update belongs to (rowKey(flowId, row)), at most 200 characters. With phase and target it is the update’s identity: once a request. Required.
The record to update. Once a request: two updates of one record go in two calls, in order. Required.
The fields to write, as the engine built them. Required.
object
write (the default) when it makes the row’s change to the record, patch when it fills one field the engine could only fill after the save, as a single update.
Example
patchFor a patch, the field it fills; required with phase: patch (TARGET_REQUIRED).
Example
Parent_AccountThe (field, value) pairs the engine indexed the record under, as a single update keeps them.
Example
[ [ "Account_Number", "ac-1" ]]Responses
Section titled “Responses”One result per update, in the order sent.
object
object
Zoho declined this update, or said nothing of what was done with it (zoho.unanswered), exactly as a single update relays it — the record’s own result inside the batch’s answer, or the whole call’s failure, which is every record’s.
object
object
True when Zoho gave no answer that says what was done — the connection dropped or timed out, Zoho failed on its side (a 5xx, or the same for the one record inside a 2xx), the answer was lost after its status or was not JSON, or Zoho said it made the record without saying which — so what was asked may have been done all the same: a create sent again after one may make a second record. A write that went unanswered stays counted, and its row may be written again for nothing. False when Zoho answered by declining (a 4xx, or a per-record refusal inside a 2xx), which made nothing.
True when Zoho asked for fewer calls and declined this one (TOO_MANY_REQUESTS): nothing was done, and the same call a little later may land — a write included, since a declined one made nothing. Absent from an older API.
How long Zoho asked to be left alone before the next call, in milliseconds, from its Retry-After; also sent as this response’s own Retry-After, in seconds. Null when it said nothing.
True when the rate limit is the CRM’s daily allowance of API calls used up — a 429 whose X-API-CREDITS-REMAINING says none are left — which waiting seconds does not bring back. Without that header the two limits cannot be told apart, and this is false.
Not sent: the run reached the rows it may write (RUN_STOPPED). A row this run had already counted is still written; a new one is not.
object
object
Not sent: this row already has a different record in this module under this run.
object
Not sent: the tenant’s gate refused it, because the connected system said a daily allowance it draws on is spent (DAILY_ALLOWANCE_SPENT). Nothing was written, and it is refused until the allowance renews.
object
Example
{ "results": [ { "ok": true } ]}No items, more than 10 (BATCH_SIZE), an update with no payload, row key or record, a patch that names no field (TARGET_REQUIRED), or one named twice (ROW_KEY_REPEATED, RECORD_REPEATED). Nothing was admitted or sent. Or the module is a subform (SUBFORM_NOT_WRITABLE, written: false): its rows are written inside their parent’s record, never as records of their own.
object
Example
{ "written": false}No bearer, or one that no longer resolves: a session that is unknown or expired (code: AUTH_REQUIRED), or an API token that was revoked or expired (TOKEN_REVOKED, TOKEN_EXPIRED), whose organisation is gone (ORG_NOT_FOUND) or whose member or user row is (MEMBERSHIP_GONE).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The run has been stopped and nothing was written (code: RUN_STOPPED, with stop); the run is an import’s and this is not the session or token that authorised it (code: NOT_YOUR_RUN); or the bearer’s role is too low, or it was issued for a different organisation. Like every route behind a session: a session signed in but in no organisation is refused code: NO_ORG, a banned person code: BANNED, and a closed organisation code: ORG_CLOSED.
object
object
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Example
{ "code": "RUN_STOPPED", "stop": { "stopped": "LIMIT_ROWS_PER_RUN", "stoppedBy": "plan" }}No such connector, or it is not visible to this session (NOT_FOUND); no such run (RUN_NOT_FOUND); or the connection has no module of that name — only its modules, as its discovery read them, are asked of the CRM (MODULE_NOT_FOUND).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The run is not authorised to write, the run is no longer authorised, the run was authorised for a different connector (RUN_CONNECTOR_MISMATCH), or the run is an import’s and no longer holds it — its lease ran out and the import was released (LEASE_LOST).
object
Examplegenerated
{ "error": "example"}Zoho is throttling how often this connection’s access is renewed — ten tokens from one grant in ten minutes — so nothing was sent (code: CONNECTION_THROTTLED; written: false on a write). Retry-After says when to ask again. The connection is kept: only a grant Zoho refuses ends it. A renewal throttled after the call reached Zoho is Zoho’s rate limit, relayed as a 502 with zoho.rateLimited.
Or the CRM’s API allowance for the last 24 hours is spent (zoho.quotaSpent: true, zoho.rateLimited: true, zoho.retryable: false), said one of two ways. Zoho itself refused the call (zoho.code: TOO_MANY_REQUESTS, credits left 0): relayed as this 429, never a 502, since asking again soon is refused again. Or the tenant’s gate refused it before it was sent, because Zoho had already said so: this API’s own refusal, with no zoho (code: DAILY_ALLOWANCE_SPENT; written: false on a write). Neither carries Retry-After: Zoho’s day is a rolling 24 hours and it names no time at which credits return, so Sloose lets one call a minute through to ask, and the first one answered is the allowance’s return. GET …/credits says whether the day is held spent (spent, spentAt). A system that does name its renewal is answered with Retry-After until then.
object
Why: CONNECTION_UNAVAILABLE (502) when a Zoho token for the connection will not refresh, CONNECTION_THROTTLED (429) when Zoho is throttling its renewal — ten tokens from one grant in ten minutes — and the connection is kept, and DAILY_ALLOWANCE_SPENT (429) when the connected system said a daily allowance the call draws on is spent, which waiting seconds does not bring back.
On a write: refused before the record was sent to the CRM, so nothing was written and a retry makes no second record. Absent from a read.
Example
{ "written": false}Zoho is rate-limiting (zoho.unanswered false: nothing was done), or did not answer — it could not be reached, failed on its side, or answered without saying what it did (zoho.unanswered true: what was asked may have been done). Or this API could not use the connection before anything was sent — a Zoho token that will not refresh (code: CONNECTION_UNAVAILABLE) — and says so on a write with written: false: nothing was written.
object
object
True when Zoho gave no answer that says what was done — the connection dropped or timed out, Zoho failed on its side (a 5xx, or the same for the one record inside a 2xx), the answer was lost after its status or was not JSON, or Zoho said it made the record without saying which — so what was asked may have been done all the same: a create sent again after one may make a second record. A write that went unanswered stays counted, and its row may be written again for nothing. False when Zoho answered by declining (a 4xx, or a per-record refusal inside a 2xx), which made nothing.
True when Zoho asked for fewer calls and declined this one (TOO_MANY_REQUESTS): nothing was done, and the same call a little later may land — a write included, since a declined one made nothing. Absent from an older API.
How long Zoho asked to be left alone before the next call, in milliseconds, from its Retry-After; also sent as this response’s own Retry-After, in seconds. Null when it said nothing.
True when the rate limit is the CRM’s daily allowance of API calls used up — a 429 whose X-API-CREDITS-REMAINING says none are left — which waiting seconds does not bring back. Without that header the two limits cannot be told apart, and this is false.
object
Why: CONNECTION_UNAVAILABLE (502) when a Zoho token for the connection will not refresh, CONNECTION_THROTTLED (429) when Zoho is throttling its renewal — ten tokens from one grant in ten minutes — and the connection is kept, and DAILY_ALLOWANCE_SPENT (429) when the connected system said a daily allowance the call draws on is spent, which waiting seconds does not bring back.
On a write: refused before the record was sent to the CRM, so nothing was written and a retry makes no second record. Absent from a read.
Example
{ "written": false}The restore switch is on (code: MAINTENANCE): every route but /health and /robots.txt is refused before anything is read, except the operator’s own POST /staff/people/{id}/delete with the ADMIN_TOKEN. Sloose is down for maintenance. Please try again in a few minutes.
object
Example
{ "code": "MAINTENANCE"}Headers
Section titled “Headers”Seconds until asking again is worth it (300 while the switch is on).