pk_live_...) are public credentials that the
embeddable web widget uses from the browser. Unlike secret API keys,
they are scoped to a specific agent (or a webhook that will dynamically
resolve one) and gated to a list of allowed origins — safe to ship in
your front-end code.
Each key is associated with exactly one of:
mode = "agent": fixed binding to an agent id. Simplest setup.mode = "webhook": the widget calls yourcall.incomingwebhook to dynamically resolve an agent per visitor.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/publishable-key | List publishable keys |
POST | /v1/publishable-key | Create a publishable key |
GET | /v1/publishable-key/{key_id} | Retrieve a key |
PATCH | /v1/publishable-key/{key_id} | Update name / allowed domains / mode |
DELETE | /v1/publishable-key/{key_id} | Deactivate a key |
POST | /v1/publishable-key/{key_id}/transfer | Copy or move to another org |
Publishable key object
| Field | Type | Description |
|---|---|---|
id | integer | Key id |
name | string | Display name |
key | string | The raw pk_live_... value. Publishable keys are public, so the full value is retrievable at any time |
key_prefix | string | First 12 chars for display (e.g. pk_live_abc) |
allowed_domains | array of string | Origin allowlist — exact hostnames and *.subdomain wildcards. localhost/127.0.0.1 always allowed |
is_active | boolean | false after deactivation; a deactivated key stops working |
is_enabled | boolean | Temporary disable toggle (separate from is_active) |
mode | string | agent or webhook |
agent_id | integer | null | Required for mode="agent" |
webhook_url | string | null | Required for mode="webhook" — overrides the org-level webhook |
created_at, updated_at | timestamp |
List publishable keys
Create a publishable key
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | Defaults to "Web Widget" |
mode | string | no | agent (default) or webhook |
agent_id | integer | yes (if mode="agent") | |
webhook_url | string | yes (if mode="webhook") | HTTPS URL |
allowed_domains | array of string | yes | At least one entry required. See rules below |
is_enabled | boolean | no | Defaults to true |
Allowed-domain rules
- An exact match:
example.com - A wildcard match:
*.example.com(matchesapi.example.combut not bareexample.com) localhostand127.0.0.1are always allowed during local dev, regardless of the list- Bare wildcards (
*or*.*) are rejected with400 - At least one entry is required — passing an empty array returns
400 allowed_domains: "At least one allowed domain is required."
201 Created with the new Publishable key object.
The key field is included on creation and is retrievable later
via GET — publishable keys are public by design.
Update / delete
PATCH accepts any subset of name, allowed_domains, mode,
agent_id, webhook_url, is_enabled. Switching between modes
requires providing the new required field (agent_id or
webhook_url).
DELETE sets is_active=false — the key stops working but remains
visible in list responses so you can audit prior deployments. There is
no hard delete.
Transfer a publishable key
| Field | Type | Required | Description |
|---|---|---|---|
target_org_id | integer | yes | |
mode | string | yes | copy or move |
name | string | no | Override the copy’s name |
Related
Widget overview
How the widget uses
pk_live_ keys at runtime.Dynamic webhook config
Shape the
call.incoming webhook must respond with in webhook mode.