https://api.quiva.ai and JSON bodies. Authenticate with an integration token.
The task routes return the object itself, for example a task or
{"results": [...]}. Only the accounts routes for managing integrations wrap success in {"data": ...}. Every error is {"error": "<text>", "code": "<code>"}.The pieces
Versions and conditional writes
Every task has an integerversion. It is 1 when the task is created and goes up by one on every write to the task, including a status change made by ticking a task action. It appears in every response and every event.
Comments, time logs, adding or deleting an action and activity stamps do not change version. They move activity_at instead.
Send If-Match: <version> on PATCH or DELETE of a task, or on the upsert, to say “only apply this if the task is still at the version I read”.
"4" is accepted, and If-Match: 0 matches an older task that has no version yet.
External ids and the upsert
Anexternal_id is your id for a task: up to 256 bytes of UTF-8, any characters except /. Characters such as : and . are fine. Percent-encode the id in the URL path.
- The id belongs to one Space. The same external id in another Space is a different task.
- An integration has its own namespace of ids. Callers that are not integrations share one.
- A task that is mapped keeps its external id. A
PATCHthat changes or clears it returns409 external_id_immutable. Sending the same value is harmless. - You can find a task by id:
GET /workspaces/space/OPS/tasks?external_id=ticket-9041is an exact match. - Setting
external_idon a task through create orPATCHwithout the upsert stores a plain attribute. It does not claim the id and is not unique.
Strict ids for integrations
When an integration writes, a status, priority or tag that the Space does not define is refused with400 unknown_status, unknown_priority or unknown_tag. Ids are compared, not names. An empty value clears the field. On a move, the destination Space’s lists apply.
Activity and listing
activity_at equals updated_at after a task write, and also moves when a comment, time log or action is written. Sort by it to find recent work:
{"results": [...], "results_total": n}. results_total is the number of tasks on this page, not a total. When more tasks exist, the response includes "has_more": true. The field is left out when there are no more, so treat a missing has_more as false. Page with offset. The default limit is 300.
Read the changes feed
GET /workspaces/space/{space_id}/changes returns every task, comment and action write in a Space, deletes included, in order. It needs tasks:read.
taskis always the whole task after the change, never a delta.- When
has_moreis true, call again straight away withnext_cursor. - An empty page still returns a
next_cursor. Store it, so an idle Space’s cursor stays inside the retention window. - History is kept for 30 days. An older cursor returns
410 cursor_expiredwith a freshnext_cursorandretention_days. The events in the gap are gone, so list the Space to catch up, then resume from the new cursor. - The feed does not hide your own writes. Skip events whose
originis your integration. - A feed scoped to a Space also receives
task-movedwhen a task leaves it.
Event types
Who made the change
origin says where a write came from, which lets you ignore your own.
A minimal sync loop
This loop pulls changes from Quiva, pushes your system’s changes with the upsert, and avoids echoing its own writes.pull on a timer, or trigger it from a webhook. Test the whole loop against a staging Space first.
Connector sync engine
If your other system is an item tracker, you may not need to write a sync at all. A connector with async block keeps a Space and the tracker in step in both directions, using these same features underneath: external ids, versioned writes, the changes feed and signed webhooks.
A connected tracker has its own integration and task subscription, which you can see in the integration’s delivery log. A task subscription can deliver to a connector’s sync address instead of your own endpoint; the engine verifies it and runs the push for you.
Related
Task webhooks
Push the same events to your endpoint, signed.
Connect a tracker
The no-code option for a supported tracker.
Errors and limits
Every code the sync routes return.
Workspaces API
The full route reference.
Tasks
Fields on a task and how they work in the app.