Skip to content

Bulk operations

The public API currently exposes three bulk write operations:

Each bulk operation mirrors one granular write action and applies its exact update shape. It does not introduce a second action enum or new writable fields. Validation, permissions, visibility, and state rules stay aligned with the corresponding single-resource operation:

  • The clients bulk operation uses the client update fields, such as status, priority_level, tags, assigned_to, and field_values.
  • The tasks bulk operation uses the tasks.manage shape, so each item’s set requires an action of update_status, assign, or set_due_date plus that action’s fields.
  • The tickets bulk operation uses the ticket update fields, such as status, priority, client_id, and assigned_to.

A bulk write accepts an items array in which every item carries its own target ID and its own set:

{
"items": [
{
"id": "11111111-1111-4111-8111-111111111111",
"set": {
"action": "update_status",
"status": "completed"
}
},
{
"id": "22222222-2222-4222-8222-222222222222",
"set": {
"action": "set_due_date",
"due_date": "2026-08-15T17:00:00Z"
}
}
]
}
  • items is required and accepts 1 through 100 entries.
  • Each item’s set uses the writable fields from the mirrored granular operation. Use the exact set schema published for the chosen operation; different bulk operations support different fields.
  • When the same ID appears more than once, the first occurrence wins and the resource is processed at most once.
  • A request with more than 100 items is rejected at the envelope level. Split larger jobs into batches of at most 100.

The batch is authorized once, then items are processed sequentially in request order through the same code path as the single-resource operation.

An accepted batch returns HTTP 200 even when some items fail. Inspect every result and the summary:

{
"data": {
"results": [
{
"id": "11111111-1111-4111-8111-111111111111",
"success": true
},
{
"id": "22222222-2222-4222-8222-222222222222",
"success": false,
"error": {
"code": "not_found",
"message": "Resource not found."
}
}
],
"summary": {
"total": 2,
"succeeded": 1,
"failed": 1
}
}
}

Partial success is normal. A per-item failure does not roll back successful items, does not stop later items, and does not fail the batch response. Per-item error.code values are validation_error, not_found, permission_denied, rate_limited, conflict, and internal.

Non-200 responses are reserved for envelope-level failures, such as a malformed body, an over-cap request, or a caller that lacks the required permission entirely. If a batch is accepted, retry only the failed IDs after deciding whether each item error is retryable.

Re-submitting an item runs the single-resource setters again. Values that already match are accepted, but the underlying write may refresh timestamps, task completion validation still applies, and ticket assignment updates may add assignment history. There is no cross-request dedupe, so the caller owns idempotency across batches.

  • Keep a client-side record of each resource ID and its desired change.
  • Persist the returned per-item status before starting the next batch.
  • Retry transient failures separately from validation, permission, conflict, and not-found failures.
  • Re-read records when state may have changed since the batch was prepared.
  • Stay within the API rate-limit headers described in the API Quickstart.