Requests, responses, pagination, and errors
Bergur DavidsenUpdated 2026-07-14
Usable REST routes share HTTP conventions, but they do not all return one universal envelope. Generate or validate client code against GET /api/docs from the deployed environment and handle each endpoint's documented shape.
Build valid requests
For JSON writes:
Content-Type: application/json
Accept: application/json
Authorization: Bearer <personal-access-token>Validate before sending:
- UUID fields and path parameters;
- required workspace IDs;
- enums such as status and sort order;
- array encoding for tags or MIME types;
- string and content limits;
- mutually exclusive fields;
- method and route path.
File uploads use multipart form data. Downloads can return binary bodies. Do not force every response through a JSON parser.
Response envelopes vary
For example, released fragment listing returns a collection shape with fragment and pagination fields, while single-fragment retrieval wraps the resource with fields such as success and fragment.
A create operation can return an ID and status: "processing" rather than the final resource. A delete operation may archive or soft-delete depending on its contract.
Avoid generic assumptions such as:
all resources live in response.data
all 2xx responses are complete
all DELETE calls remove immediatelyParse the endpoint schema and refetch when final state matters.
Pagination
Released fragment listing uses limit and offset:
curl "https://usable.dev/api/memory-fragments?workspaceId=<workspace-id>&limit=50&offset=0" \
-H "Authorization: Bearer <personal-access-token>"The fragment list's documented limit range is 5–500. Other endpoint limits can differ.
A robust loop:
- Start at offset 0.
- Use a bounded limit accepted by that endpoint.
- Process the returned page.
- Advance by the returned count, not the requested limit.
- Stop when
offset + count >= totalCount. - Preserve a stable sort where supported.
Do not assume a hasMore field exists. Data can change while offset pagination runs, so use stable keys or timestamps for synchronization where the route supports them.
Asynchronous operations
Fragment enrichment, file processing, workspace creation, invitation revocation, and other workflows can return processing.
When an operation is accepted:
- store the returned resource or operation ID;
- poll the documented read/status route;
- use bounded exponential backoff with jitter;
- set an overall timeout;
- stop on success or terminal failure;
- do not duplicate the write because the first response was not final.
A client timeout does not prove the server discarded the request.
Idempotency and safe retries
Retry reads after transient network errors. Retry writes only when the endpoint documents idempotency or your application can detect prior completion.
For fragment imports:
- use a stable workspace-scoped
keywhere appropriate; - search or fetch before repeating creation;
- store returned fragment IDs;
- send deterministic
summaryandtagswhen exact metadata matters.
For updates, refetch before replacing content and use patch semantics supported by the endpoint. Do not overwrite concurrent work with stale state.
Common status codes
200— request succeeded; inspect the body.201— resource creation accepted or completed.202— accepted with further processing or partial side-effect status.400— invalid request, field, encoding, or limit.401— missing or invalid authentication.403— authenticated but not authorized.404— absent, deleted, or hidden resource.409— state, placement, or conflict condition.429— rate limit where enforced; follow documented retry headers.500— unexpected server failure.
Do not publish or hard-code a global rate limit unless the deployed contract documents one. Limits can vary by route and environment.
Typed errors
Some routes return a machine-readable code alongside a human-readable error. Branch on the documented code, while retaining a safe fallback for unknown values.
Hosted Zone boundary responses can include HOSTED_ZONE_REQUIRED with placement information. This is a routing instruction, not a reason to send private workspace data to Cloud.
MCP is different: POST /api/mcp can return HTTP 200 while a tool result contains isError: true. Parse the JSON-RPC result before treating an MCP call as successful.
Log safely
Useful diagnostic fields include:
- method and route template;
- status code;
- target environment and platform version;
- workspace and resource IDs when policy permits;
- elapsed time and retry count;
- documented request or correlation ID where present.
Never log bearer tokens, cookies, full private content, file bytes, signed URLs, or raw provider errors containing secrets.
Troubleshooting
400 on a list request
Check minimum/maximum limit, UUID format, repeated versus encoded array parameters, and enum values.
405 Method Not Allowed
Confirm the REST route rather than translating an MCP tool name into a path. For example, REST fragment listing is GET /api/memory-fragments.
2xx but no final resource
Inspect status, retain the returned ID, and poll or refetch the documented resource.
Response parser fails
Compare the actual body and content type with /api/docs. Lists, single resources, binary downloads, and JSON-RPC responses differ.