Chattr

Partner API Reference

REST / JSON 60 req/min per key Base URL: https://chattr.ge

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_...
AbilityGrants
sites:writePOST /v1/tenants — provision/update a site
documents:writePUT/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).

Every endpoint returns the same envelope as the rest of the Chattr API: { "success": bool, "data": ..., "message": string|null }. Validation errors return 422 with an errors object.

Provision a Site

POST /v1/tenants Requires 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

PUT /v1/tenants/{externalRef}/documents Requires 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

POST /v1/tenants/{externalRef}/documents/delete Requires 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

GET /v1/tenants/{externalRef}/widget-config Any valid key that owns this tenant
{ "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}.