Conventions
Field casing
Section titled “Field casing”All request and response fields use snake_case — e.g. due_date, task_status_id.
Response envelopes
Section titled “Response envelopes”Successful responses are wrapped in a data envelope:
{ "data": { "id": "task_6a2918cff58b0a1d387866ee" } }List endpoints add a pagination object:
{ "data": [ /* … */ ], "pagination": { "next_cursor": "…", "has_more": true }}Errors use a separate envelope — see Errors.
Pagination
Section titled “Pagination”List endpoints are cursor-paginated. Pass the next_cursor from the previous response to fetch the next page; has_more tells you when to stop. Treat the cursor as opaque.
Idempotency
Section titled “Idempotency”POST requests (creates) accept an Idempotency-Key header. Send a unique key (up to 255 characters — a UUID works well) so a retried request can’t create a duplicate:
curl -X POST https://api.bordio.com/public/v1/tasks \ -H "Authorization: Bearer brd_sk_live_..." \ -H "Idempotency-Key: 6a2918cf-f58b-0a1d-3878-66ee00000001" \ -H "Content-Type: application/json" \ -d '{ "title": "New task" }'How it behaves:
- Same key, same body → the original result is replayed; nothing new is created.
- Same key, different body →
409 conflict_error(already_exists). - Same key while the first request is still in flight →
409 conflict_error— retry once the first one finishes. - Keys are remembered for 24 hours, then expire — reusing a key after that is treated as a brand-new request.
- A key is scoped to its endpoint (and workspace): the same key on a different endpoint is independent.
- Only
POSTis idempotent via this header.PATCH/DELETEare not — aPATCHis naturally safe to repeat, since it sets fields to the values you send.