API and webhooks

Issue a workspace token, list and reply to conversations over HTTPS, and verify signed events when a thread is handed off, resolved, or rated.

Where it lives

API in the workspace sidebar — /workspaces/:id/api. It is owner-only, like Site keys and Team. You need an active subscription to create or revoke a token or register a webhook. The page is visible either way.

Create a token

Name the token and choose the scopes it may use. Doorwick shows the plaintext value once — dw_ followed by hex. Copy it into your secret manager. After that, only a SHA-256 digest is stored, so it cannot be recovered from the dashboard.

conversations:read
List conversations and read a thread, including visitor-visible messages.
conversations:write
Post an operator reply. Visitors see it in the widget.
conversations:resolve
Resolve a conversation or reopen it.
Content synchronization
A preset of eight narrow scopes for managed knowledge, AI readiness, the system prompt, visitor quick actions, previews, and run history.

Send it as Authorization: Bearer dw_… to https://chat.doorwick.com/v1. Revoke a token from the same page when you rotate it.

Validate a newly configured integration with GET /v1/token. It returns the token name and scopes, its workspace, and supported content/webhook schema versions without returning any secret. The machine-readable contracts are published as OpenAPI and a manifest JSON Schema.

Treat the token like a password. Do not put it in browser code, a site key field, or a public repository.

Synchronize public content

Managed Content Sync coordinates versioned knowledge sources, the system prompt, and visitor quick actions. It previews every action before applying, rejects stale previews, and never treats omission as permission to retire content by default. Read the Managed Content Sync guide.

POST /v1/ai_readiness_probes
Tests harmless chat and embedding calls and returns safe, actionable provider codes.
GET /v1/knowledge_readiness
Reports the strict visitor-AI gate, indexed counts, provider health, latest release, retry timing, and limits.
POST /v1/content_sync_runs/:id/retry_attempts
Retries failed staged items only; it never rewrites already verified items.
POST /v1/knowledge_reindexings
Queues a bounded whole-collection or failed-only recovery.

List conversations

GET /v1/conversations returns the workspace inbox, newest activity first. Filter with status=open, pending_human, or resolved. Page with cursor and limit (default 20, max 50).

curl
curl -s https://chat.doorwick.com/v1/conversations?status=pending_human \
  -H "Authorization: Bearer $DOORWICK_API_TOKEN"

Read a thread

GET /v1/conversations/:id returns the contact, status, and visitor-visible messages. Internal operator notes are not included.

curl
curl -s https://chat.doorwick.com/v1/conversations/42 \
  -H "Authorization: Bearer $DOORWICK_API_TOKEN"

Reply as an operator

POST /v1/conversations/:id/messages with { "body": "…" } posts a reply the visitor can see — the same as sending from the inbox. Needs conversations:write. A reply to a resolved thread reopens it.

curl
curl -s https://chat.doorwick.com/v1/conversations/42/messages \
  -H "Authorization: Bearer $DOORWICK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"We are looking into this and will update you shortly."}'

Resolve and reopen

Both need conversations:resolve.

POST /v1/conversations/:id/resolve
Marks the thread resolved and tells the widget so it can offer a rating.
POST /v1/conversations/:id/reopen
Opens a resolved thread again.

Errors

Requests without a token, or with an unknown token, return 401. A valid token missing the scope for that action returns 403. An id from another workspace returns 404 — Doorwick does not confirm that the conversation exists.

Error bodies contain a stable code plus a human-readable error. A rate-limited request returns 429 and Retry-After. List endpoints use an opaque cursor, return next_cursor, and accept limit up to 50. Knowledge inventory can filter by management mode, collection, refresh state, and retirement; use include_content=false for metadata-only pages. Sync history can filter by collection, release, and status.

Webhooks

Register an HTTPS URL and the events you want. Doorwick shows the signing secret once. The events are:

conversation.escalated
Status became pending_human.
conversation.resolved
Status became resolved.
conversation.rated
A CSAT score was recorded.
ai.no_answer
Knowledge retrieval found nothing relevant for a visitor question.
content_sync.succeeded
A managed release completed successfully.
content_sync.partially_failed
Only optional managed sources failed.
content_sync.failed
A required source or deterministic verification failed.

A delivery looks like:

JSON body
{
  "id": "4d3a20b3-610f-4ed0-b599-45cf131b5b88",
  "delivery_id": "6dc84df3-1c1d-44e4-a1fc-8f6dcadf3401",
  "schema_version": 1,
  "event": "conversation.escalated",
  "sent_at": "2026-08-21T19:00:00Z",
  "data": {
    "conversation": {
      "id": 42,
      "status": "pending_human",
      "handler": "human",
      "contact": { "id": 7, "email": "sam@example.com", "name": "Sam" }
    }
  }
}

Verify the signature

Every delivery is HMAC-signed with the endpoint secret. Reject timestamps older than about five minutes so a captured request cannot be replayed.

X-Doorwick-Timestamp / X-Webhook-Timestamp
Unix seconds
X-Doorwick-Event-ID
Stable event identifier; use it to deduplicate side effects.
X-Doorwick-Delivery-ID
Unique identifier for this endpoint delivery.
X-Webhook-Signature-V2
hex HMAC-SHA256(secret, "{timestamp}.{body}")
X-Doorwick-Signature
the same digest, prefixed sha256=
X-Doorwick-Event
the event name
verify.rb
require "openssl"

def doorwick_signature_valid?(secret, timestamp, body, signature)
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, [timestamp, body].join("."))
  provided = signature.to_s.delete_prefix("sha256=")
  OpenSSL.fixed_length_secure_compare(expected, provided)
end

Doorwick retries network errors, 408, 425, 429, and 5xx responses up to five attempts and honors a bounded Retry-After. Other 4xx responses are terminal. The API page shows durable attempt evidence and allows an owner to replay while the separately encrypted payload is retained for seven days.

Next