Conventions
How requests and responses are shaped in the Lookio API, with pagination, idempotency keys, request IDs, read-after-write and the forgiving and strict input rules.
Requests and responses
- Send JSON with
Content-Type: application/json. A body without the header is accepted if it parses. - Fields are
snake_case, in requests and responses. - Object IDs have a type prefix and twelve random lowercase letters or digits, such as
ast_k7m3x9p2w8qrfor an assistant orres_h4n8c2v6y9tkfor a resource. They stay unchanged when renamed. Widgets use the samewdg_…id in the API, embed snippets and hosted URLs. Treat IDs as opaque strings. Timestamps are ISO 8601 strings in UTC. - A JSON body is limited to 1 MB. A file goes in a separate upload call.
- A trailing slash is tolerated:
/v1/account/and/v1/accountare the same endpoint. - Responses carry
Cache-Control: no-store.
A success wraps the result:
{
"data": { },
"request_id": "req_0123456789abcdef0123456789abcdef"
}A list adds has_more, next_cursor and limit next to data. Each endpoint page shows the exact shape of data.
Inputs: forgiving, then strict
- A missing optional field takes its documented default.
- A
limitabove the maximum is clamped, and the response reports the limit actually applied. - An unknown field in a JSON body fails with
unknown_field, at any depth (a field insiderulesis namedrules.exlude). The message suggests the closest valid name: sendingfollowTagsanswers “Did you mean ‘follow_tags’?”. - An unknown query parameter is ignored, so a tracking parameter appended by a proxy does not break a call. A mistyped filter therefore returns an unfiltered result.
- Only the first problem is reported, so you fix one thing at a time.
Pagination
Lists of resources use a cursor.
| Parameter | Meaning |
|---|---|
limit | 1 to 100, default 25. |
cursor | The next_cursor of the previous page, passed back unchanged. |
curl "https://api.lookio.app/v1/resources?limit=50" \
-H "Authorization: Bearer $LOOKIO_API_KEY"Results come newest first. While has_more is true, call again with cursor set to next_cursor. A cursor that matches nothing fails with invalid_cursor.
Other lists (assistants, tags, members) are returned whole, in one response.
Idempotency
Networks fail, and automation tools retry. Without protection, a retried import creates a duplicate resource and a retried question is charged twice.
Add an Idempotency-Key header to a POST. Lookio runs the request once, and a repeat with the same key returns the first response with an Idempotent-Replayed: true header.
curl https://api.lookio.app/v1/assistants/ASSISTANT_ID/query \
-H "Authorization: Bearer $LOOKIO_API_KEY" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "Content-Type: application/json" \
-d '{ "question": "How long do I have to return an item?" }'The rules:
- The key is 1 to 255 visible ASCII characters. A UUID is a good choice. Generate a new one for each distinct request and reuse it only for retries of that request.
- Keys belong to one credential and live 24 hours.
- The same key on a different request (method, path, query or body) fails with
conflict. - While the first request is still running, a retry fails with
conflict. Wait a few seconds and retry. - A refusal (4xx) is an answer and is replayed as such. A
5xxor a429is not kept and frees the key, so a retry really retries. - A response is kept only if it is JSON and under 256 KB.
- A file upload is fingerprinted by its name, size and query, not by its bytes.
The CLI sends a fresh Idempotency-Key on every POST and reuses it across its automatic retries.
Request IDs
Every response has an X-Request-Id header and, for JSON, a request_id field. It looks like req_ followed by 32 hex characters. Lookio generates it. You cannot supply one.
Log it. It identifies the request on Lookio’s side without exposing your key or your content, and it is what support asks for.
Read after write
An import returns before it is read, and a resource you create can be asked for right away. Every response carries an X-D1-Bookmark header. Send the last one you received back as X-D1-Bookmark on your next request, and Lookio reads at least as fresh as your last write. Without it, a read made immediately after a write can occasionally be served from a replica that has not caught up. A malformed value is ignored.
Asynchronous work
Importing is asynchronous. A resource comes back as queued, and you poll GET /v1/resources/{resource_id} until status is ready or failed. Both are final: do not poll past them. An assistant cannot answer from a resource that is not ready.
Costs
Only asking an assistant spends credits. Every endpoint page says so when it matters, and the answer reports credit_cost.