Partner API Reference
Build a product on top of Chattr — provision a site and push knowledge-base content programmatically instead of clicking through the dashboard. This is a self-service, server-to-server API: any Chattr account can mint a partner key from Profile → Partner API Keys, no approval needed. For the authenticated operator/Android API, see the Operator API docs; for the anonymous visitor-facing widget, see the Widget API docs.
Authentication
Create a partner API key from Profile → Partner API Keys. A key is a service account distinct from the personal API tokens on the same page — it doesn't stand in for a logged-in operator, and it only has the abilities you grant it at creation.
Authorization: Bearer pk_live_...
- The plaintext key is shown once, at creation — Chattr only stores its hash.
- Missing or invalid keys return
401; a key lacking the ability a route requires returns403. - A banned account's keys stop working immediately, same as its operator login.
| Ability | Grants |
|---|---|
sites:write | POST /v1/tenants — provision/update a site |
documents:write | PUT/POST /v1/tenants/{externalRef}/documents... — manage knowledge-base content |
GET .../widget-config needs no ability beyond a valid key that owns the referenced tenant — site_key is already meant to be public, the same value the dashboard's own embed code exposes.
Tenants & external_ref
Every site a partner key touches is addressed by your own external_ref, not Chattr's internal site id — you never need to store a Chattr-assigned id anywhere. It's scoped to your account: two different partner accounts can each use "tenant-1" without colliding, and a key can never see or act on a site outside its own account (a mismatched external_ref returns 404, indistinguishable from a nonexistent one).
{ "success": bool, "data": ..., "message": string|null }. Validation errors return 422 with an errors object.
Provision a Site
sites:write
Idempotent on (your account, external_ref) — call it again any time your tenant's name or domain changes; it updates in place rather than erroring or duplicating.
{ "external_ref": "tenant-123", "name": "Acme Coaching", "domain": "acme.example.com" }
Response 201:
{
"success": true,
"data": {
"id": 42,
"external_ref": "tenant-123",
"name": "Acme Coaching",
"domain": "acme.example.com",
"site_key": "b6e1...-uuid",
"widget": { "widget_id": "b6e1...-uuid", "api_url": "https://chattr.ge" }
},
"message": null
}
Upsert Documents
documents:write
max 200 per call
Bulk upsert-by-your-own-id. Each document is a full replacement — send the complete current content every time, not a diff. Safe to retry: replaying the same call re-embeds the same content.
{
"documents": [
{ "id": "page-1", "title": "Pricing", "content": "Our plans start at...", "url": "https://acme.example.com/pricing" }
]
}
url is optional — a reference link shown alongside the content, never fetched by Chattr. Content is chunked and embedded asynchronously; the dashboard's Knowledge Base tab reflects status once processing completes.
Delete Documents
documents:write
{ "ids": ["page-1", "page-2"] }
Deletes each matching document (and its embedded chunks). Ids that don't exist are silently skipped — safe to retry.
Get Widget Config
{ "success": true, "data": { "widget_id": "b6e1...-uuid", "api_url": "https://chattr.ge" }, "message": null }
Embed the widget the same way the dashboard's own embed-code generator does, using widget_id as the site parameter: {api_url}/widget.js?site={widget_id}.