The items API
An item is the placeholder resource of the boilerplate: a name, a description, a status and at most one file. The dashboard calls the same endpoints under /api/v1/items with a session; your server calls them under /v1/items with an API key.
Every request sends the key in the Authorization header:
Authorization: Bearer acme_live_...
The OpenAPI document is published at /docs/api/openapi.json.
The item
| Field | Type | |
|---|---|---|
id | string | The item's id. |
name | string | 1 to 120 characters. |
description | string | Up to 2,000 characters, empty when there is none. |
status | active or archived | An archived item stays readable and stops counting as active. |
file | object or null | {name, type, size} of the attached file. |
createdBy | string or null | The member who created it. |
createdAt, updatedAt | integer | Milliseconds since 1970, UTC. |
Endpoints
| Method and path | Scope | Credits |
|---|---|---|
GET /v1/items | items:read | 0 |
GET /v1/items/:id | items:read | 0 |
POST /v1/items | items:write | 1 |
PATCH /v1/items/:id | items:write | 1 |
DELETE /v1/items/:id | items:write | 0 |
PUT /v1/items/:id/file | items:write | 1 |
GET /v1/items/:id/file | items:read | 0 |
List items
GET /v1/items answers the newest items first, 50 at a time:
{ "items": [{ "id": "0199f0a2-7c1e-7b3a-9d2f-4e5a6b7c8d90", "name": "..." }], "next": "eyJ..." }
Query parameters, all optional:
limit: 1 to 200, 50 by default.cursor: thenextvalue of the previous page.nextisnullon the last page.status:activeorarchived.search: matches the name, up to 120 characters.
Create an item
curl https://example.com/v1/items \
-H "Authorization: Bearer $ACME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5b0c..." \
-d '{"name": "Invoice template", "description": "The one we send in January"}'
Edit, archive or restore
PATCH /v1/items/:id takes any of name, description and status:
{ "status": "archived" }
Delete
DELETE /v1/items/:id deletes the item and its file. It cannot be undone.
Attach a file
PUT /v1/items/:id/file takes the file's raw bytes as the body, up to 5 MB, and its name in the x-file-name header. A new file replaces the old one. An upload costs 1 credit, and the files of all the organization's items together stay within the plan's storage: 100 MB on Free, 10 GB on Pro, 100 GB on Business.
curl -X PUT https://example.com/v1/items/0199f0a2-.../file \
-H "Authorization: Bearer $ACME_API_KEY" \
-H "x-file-name: report.pdf" \
--data-binary @report.pdf
GET /v1/items/:id/file answers the bytes.
Retries
Send an Idempotency-Key header (1 to 200 characters) with every write. A retry with the same key is charged and written once, so a timeout is safe to retry.
Errors
An error answers a JSON body with a _tag and a message that says what to do.
| Status | _tag | When |
|---|---|---|
| 401 | Unauthorized | No key, or a key that is revoked or expired. |
| 402 | InsufficientCredits | The write costs more credits than the organization has left. |
| 403 | Forbidden | The key lacks the scope, or the member's role does not allow it. |
| 403 | OrganizationSuspended | The organization is suspended. |
| 404 | ItemNotFound | No item has that id in this organization. |
| 409 | PlanLimitReached | The plan's limit of items, or of file storage (resource: "storage"), is reached. |
| 413 | BodyTooLarge | The body is larger than allowed. |
| 422 | InvalidInput | A field is missing or out of range, the item was rejected by moderation and cannot be changed, or the Idempotency-Key was used for another kind of write. |
| 422 | ContentRefused | The Guard refused the text or the file. |
| 429 | RateLimited | Too many requests. Wait and retry. |