Documents storage
Per-account private JSON key/value storage. Your app can persist state server-side — surviving
across devices and browsers — instead of relying on localStorage. It shares the same
pipeline as every other service: rate limit → quota → bill.
Endpoints
| Method & path | Behavior |
|---|---|
PUT /api/v1/documents/:key | Upsert — the request body is the JSON value. → {key, created, chars} |
POST /api/v1/documents | Create with a generated key (d_<20hex>). → {key, created:true, chars} |
GET /api/v1/documents/:key | Returns the stored JSON verbatim. |
DELETE /api/v1/documents/:key | → {deleted:true} |
Key rules
- Keys match
^[a-zA-Z0-9._-]{1,128}$. The literals.and..are rejected (400 bad_key). - The
kb-prefix is reserved: writes/deletes tokb-*→403 reserved_key; reads are allowed. - A missing document on GET/DELETE →
404 document_not_found(not billed — only successful operations bill).
Per-key document filter
An API key scoped to the Documents service can also be restricted to a subset of document keys,
set in Dashboard → API Keys. Anything outside the filter returns
403 document_key_not_allowed — on reads, writes and deletes alike.
- The filter is a comma-separated list of patterns; the default
*allows every key. - A trailing
*matches a prefix; anything else is an exact key. Example:xxx-*, kb-*, some-specific-key. - Include
kb-usage(orkb-*) if the key should be able to read the usage document described below — that's a normal read, and the filter applies to it too. - Include
d_*if the key usesPOST /api/v1/documents, whose generated keys always start withd_— without that coverage the create is refused.
The filter only ever subtracts: it can't reach anything your account couldn't already reach, and
it doesn't lift the kb- write/delete reservation.
Limits & billing
- Value size is measured in characters (
JSON.stringify(value).length) and must not exceed the configured max (400 document_too_large). - Max documents per account is enforced when creating a new (non-
kb-) document →403 document_limit_reached. Updates to existing keys are always allowed. - Each successful op bills one unit:
doc-read,doc-write, ordoc-delete.
The kb-usage document
A read-only system document maintained per account. It lists your non-kb- documents:
{ "total": 12, "keys": ["notes", "app-state", "…"], "updated_at": "…" }
It reads like any kb- doc (billed as a read); users can't write or delete it, and it's
exempt from the size and count caps.
Examples
# Create with your own key
curl -X PUT https://khabot.com/api/v1/documents/app-state \
-H "Authorization: Bearer kb_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"theme":"dark","lastOpened":"c_42"}'
# Read it back
curl https://khabot.com/api/v1/documents/app-state \
-H "Authorization: Bearer kb_YOUR_KEY"
# List your documents
curl https://khabot.com/api/v1/documents/kb-usage \
-H "Authorization: Bearer kb_YOUR_KEY"
# Delete
curl -X DELETE https://khabot.com/api/v1/documents/app-state \
-H "Authorization: Bearer kb_YOUR_KEY"