Skip to content
Developers

Build on your support inbox.

A REST API for conversations, contacts, tickets and knowledge, signed webhooks for every important moment, and identity verification for the customers who are signed in to your website.

REST API & webhooks on Pro and aboveIdentity verification on every planOpenAPI 3.1 ↗

Authentication

Create a key in Settings → Developers → API keys and send it as a bearer token from your server. Keys are shown once and only a hash is stored. A key reaches one workspace, the websites you pick, and the areas you allow, and it acts as the teammate who made it, never above their role.

ScopeLets the key
inbox:read
inbox:write
Conversations, their messages, and tickets. Write: Reply, close, reopen and assign conversations; create and update tickets.
people:read
people:write
Contacts and their custom attributes. Write: Create, upsert and update contacts.
knowledge:read
knowledge:write
Q&A snippets. Write: Create, change and delete snippets (administrator keys).

Write includes read. The same keys also work with Chatrevia’s MCP server for AI tools, where more areas are available.

Check your key
curl https://www.chatrevia.com/api/v1/me \
  -H "Authorization: Bearer crv_sk_…"

Responses & errors

Every response is JSON. One object comes as { data }, a list as { data, has_more, next_cursor }. Times are ISO 8601 in UTC. Each response carries an X-Request-Id.

HTTPerror.type
400invalid_request
401authentication_required
403permission_denied
403plan_required
404not_found
405method_not_allowed
409conflict
422idempotency_key_reused
429rate_limited
500server_error
503unavailable
Error
{
  "error": {
    "type": "permission_denied",
    "message": "This key has no inbox:write access. Create a key with it in Settings → Developers.",
    "request_id": "req_5f0c2b7e9a1d4c3b8e6f2a10"
  }
}

Pagination

Lists are newest first and use cursors, so records never repeat or go missing while you page. Pass limit (25 by default, up to 100) and the next_cursor of the previous page as cursor until has_more is false. Add updated_after to sync only what changed.

Next page
curl "https://www.chatrevia.com/api/v1/conversations?limit=50&cursor=WyIyMDI2LTEw…" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"

Idempotency & rate limits

Send an Idempotency-Key header with any POST. If the request is retried with the same key and body within 24 hours, you get the first response back (marked Idempotent-Replayed: true) and nothing happens twice. The same key with a different body is refused with idempotency_key_reused.

Each key can make 120 requests a minute. Every response has X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; past the limit you get 429 with Retry-After.

Conversations

List conversations

GET/api/v1/conversationsinbox:read

Conversations in which the visitor has written, newest first. Previews and test chats are excluded.

website_iduuid
Only this website. Default: every website the key can use
status"open" | "needs_follow_up" | "closed"
channel"web" | "whatsapp" | "messenger" | "instagram" | "email" | "voice"
assignee_idstring
A teammate's user ID
emailstring
The visitor's email
updated_afterISO 8601 time
Only records updated after this time (ISO 8601)
created_afterISO 8601 time
Only records created after this time (ISO 8601)
limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/conversations?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "object": "conversation",
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "status": "open",
      "channel": "web",
      "visitor": {
        "name": "Maya Chen",
        "email": "maya.chen@example.com",
        "user_id": "cus_48213",
        "verified": true
      },
      "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "assignee": null,
      "taken_over": false,
      "priority": "normal",
      "tags": [
        "orders"
      ],
      "summary": "Where is my order #4417?",
      "handoff_requested_at": null,
      "snoozed_until": null,
      "csat": null,
      "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
      "closed_at": null,
      "created_at": "2026-10-04T18:20:51.000Z",
      "updated_at": "2026-10-04T18:21:07.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Get a conversation

GET/api/v1/conversations/{id}inbox:read

Request
curl "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "object": "conversation",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "status": "open",
    "channel": "web",
    "visitor": {
      "name": "Maya Chen",
      "email": "maya.chen@example.com",
      "user_id": "cus_48213",
      "verified": true
    },
    "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "assignee": null,
    "taken_over": false,
    "priority": "normal",
    "tags": [
      "orders"
    ],
    "summary": "Where is my order #4417?",
    "handoff_requested_at": null,
    "snoozed_until": null,
    "csat": null,
    "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
    "closed_at": null,
    "created_at": "2026-10-04T18:20:51.000Z",
    "updated_at": "2026-10-04T18:21:07.000Z"
  }
}

List a conversation's messages

GET/api/v1/conversations/{id}/messagesinbox:read

Oldest first. Includes visitor, AI, teammate and system messages (such as “Maya joined the chat”). Internal notes are not messages.

limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41/messages?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "6f7e8d9c-0b1a-4c2d-9e3f-4a5b6c7d8e9f",
      "object": "message",
      "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "author": {
        "type": "visitor",
        "name": null
      },
      "text": "Hi! Where is my order #4417?",
      "attachments": [],
      "channel": "web",
      "created_at": "2026-10-04T18:21:07.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Send a teammate reply

POST/api/v1/conversations/{id}/replyinbox:write

Sends a reply to the visitor as the teammate who owns the key. The teammate takes the conversation over from the AI agent, exactly as replying in the inbox does. Replies reach email and messaging-channel visitors too.

textstringrequired
The reply, plain text
Request
curl -X POST "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41/reply" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "text": "Your order shipped today. Tracking: 1Z84F2E90344172861"
     }'
Response · 201
{
  "data": {
    "id": "2b7c9e1f-3a4d-4f6b-9c8e-7d6a5b4c3e2f",
    "object": "message",
    "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "author": {
      "type": "teammate",
      "name": "Nora Patel"
    },
    "text": "Your order shipped today. Tracking: 1Z84F2E90344172861",
    "attachments": [],
    "channel": "web",
    "created_at": "2026-10-04T18:24:31.000Z"
  }
}

Close a conversation

POST/api/v1/conversations/{id}/closeinbox:write

reason"answered" | "fixed" | "feature_request" | "duplicate" | "no_response" | "spam" | "other"
Why it was resolved
notestring
Request
curl -X POST "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41/close" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "reason": "answered"
     }'
Response · 200
{
  "data": {
    "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "object": "conversation",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "status": "open",
    "channel": "web",
    "visitor": {
      "name": "Maya Chen",
      "email": "maya.chen@example.com",
      "user_id": "cus_48213",
      "verified": true
    },
    "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "assignee": null,
    "taken_over": false,
    "priority": "normal",
    "tags": [
      "orders"
    ],
    "summary": "Where is my order #4417?",
    "handoff_requested_at": null,
    "snoozed_until": null,
    "csat": null,
    "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
    "closed_at": null,
    "created_at": "2026-10-04T18:20:51.000Z",
    "updated_at": "2026-10-04T18:21:07.000Z"
  }
}

Reopen a conversation

POST/api/v1/conversations/{id}/reopeninbox:write

Request
curl -X POST "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41/reopen" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
Response · 200
{
  "data": {
    "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "object": "conversation",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "status": "open",
    "channel": "web",
    "visitor": {
      "name": "Maya Chen",
      "email": "maya.chen@example.com",
      "user_id": "cus_48213",
      "verified": true
    },
    "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "assignee": null,
    "taken_over": false,
    "priority": "normal",
    "tags": [
      "orders"
    ],
    "summary": "Where is my order #4417?",
    "handoff_requested_at": null,
    "snoozed_until": null,
    "csat": null,
    "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
    "closed_at": null,
    "created_at": "2026-10-04T18:20:51.000Z",
    "updated_at": "2026-10-04T18:21:07.000Z"
  }
}

Assign or unassign a conversation

POST/api/v1/conversations/{id}/assigninbox:write

assignee_idstring | nullrequired
A teammate's user ID, or null to unassign
Request
curl -X POST "https://www.chatrevia.com/api/v1/conversations/8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41/assign" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "assignee_id": "usr_nora"
     }'
Response · 200
{
  "data": {
    "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "object": "conversation",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "status": "open",
    "channel": "web",
    "visitor": {
      "name": "Maya Chen",
      "email": "maya.chen@example.com",
      "user_id": "cus_48213",
      "verified": true
    },
    "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "assignee": null,
    "taken_over": false,
    "priority": "normal",
    "tags": [
      "orders"
    ],
    "summary": "Where is my order #4417?",
    "handoff_requested_at": null,
    "snoozed_until": null,
    "csat": null,
    "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
    "closed_at": null,
    "created_at": "2026-10-04T18:20:51.000Z",
    "updated_at": "2026-10-04T18:21:07.000Z"
  }
}

Contacts

List contacts

GET/api/v1/contactspeople:read

People in the workspace, newest first.

website_iduuid
Only this website. Default: every website the key can use
emailstring
external_idstring
Your own user ID
updated_afterISO 8601 time
Only records updated after this time (ISO 8601)
limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/contacts?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "object": "contact",
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "external_id": "cus_48213",
      "name": "Maya Chen",
      "email": "maya.chen@example.com",
      "phone": null,
      "company": null,
      "job_title": null,
      "stage": "New",
      "tags": [],
      "score": null,
      "attributes": {
        "plan": "Barista Club",
        "lifetime_orders": 7
      },
      "verified": true,
      "verified_at": "2026-10-04T18:20:52.000Z",
      "source": "identify",
      "conversation_id": null,
      "created_at": "2026-09-12T09:14:03.000Z",
      "updated_at": "2026-10-04T18:20:52.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Get a contact

GET/api/v1/contacts/{id}people:read

Request
curl "https://www.chatrevia.com/api/v1/contacts/c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "object": "contact",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "external_id": "cus_48213",
    "name": "Maya Chen",
    "email": "maya.chen@example.com",
    "phone": null,
    "company": null,
    "job_title": null,
    "stage": "New",
    "tags": [],
    "score": null,
    "attributes": {
      "plan": "Barista Club",
      "lifetime_orders": 7
    },
    "verified": true,
    "verified_at": "2026-10-04T18:20:52.000Z",
    "source": "identify",
    "conversation_id": null,
    "created_at": "2026-09-12T09:14:03.000Z",
    "updated_at": "2026-10-04T18:20:52.000Z"
  }
}

Create or update a contact

POST/api/v1/contactspeople:write

Upserts by external_id (your own user ID), else by email. Returns 201 when a contact was created and 200 when one was updated. Custom attributes are merged.

website_iduuid
Required when the key can use several websites
external_idstring
namestring | null
emailstring | null
phonestring | null
companystring | null
job_titlestring | null
stage"New" | "Qualified" | "Contacted" | "Won" | "Lost"
tagsarray of string
attributesobject
Custom attributes to merge: string, number or boolean values; null removes one
Request
curl -X POST "https://www.chatrevia.com/api/v1/contacts" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "external_id": "cus_48213",
       "email": "maya.chen@example.com",
       "name": "Maya Chen",
       "attributes": {
         "plan": "Barista Club",
         "lifetime_orders": 7
       }
     }'
Response · 201
{
  "data": {
    "id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "object": "contact",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "external_id": "cus_48213",
    "name": "Maya Chen",
    "email": "maya.chen@example.com",
    "phone": null,
    "company": null,
    "job_title": null,
    "stage": "New",
    "tags": [],
    "score": null,
    "attributes": {
      "plan": "Barista Club",
      "lifetime_orders": 7
    },
    "verified": true,
    "verified_at": "2026-10-04T18:20:52.000Z",
    "source": "identify",
    "conversation_id": null,
    "created_at": "2026-09-12T09:14:03.000Z",
    "updated_at": "2026-10-04T18:20:52.000Z"
  }
}

Update a contact

PATCH/api/v1/contacts/{id}people:write

Changes only the fields you send. Custom attributes are merged (null removes one). Changes appear in the person's activity.

external_idstring
namestring | null
emailstring | null
phonestring | null
companystring | null
job_titlestring | null
stage"New" | "Qualified" | "Contacted" | "Won" | "Lost"
tagsarray of string
attributesobject
Custom attributes to merge: string, number or boolean values; null removes one
Request
curl -X PATCH "https://www.chatrevia.com/api/v1/contacts/c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "stage": "Qualified",
       "attributes": {
         "vip": true
       }
     }'
Response · 200
{
  "data": {
    "id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "object": "contact",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "external_id": "cus_48213",
    "name": "Maya Chen",
    "email": "maya.chen@example.com",
    "phone": null,
    "company": null,
    "job_title": null,
    "stage": "New",
    "tags": [],
    "score": null,
    "attributes": {
      "plan": "Barista Club",
      "lifetime_orders": 7
    },
    "verified": true,
    "verified_at": "2026-10-04T18:20:52.000Z",
    "source": "identify",
    "conversation_id": null,
    "created_at": "2026-09-12T09:14:03.000Z",
    "updated_at": "2026-10-04T18:20:52.000Z"
  }
}

Tickets

List tickets

GET/api/v1/ticketsinbox:read

Newest first.

website_iduuid
Only this website. Default: every website the key can use
status"submitted" | "in_progress" | "waiting" | "resolved"
conversation_iduuid
updated_afterISO 8601 time
Only records updated after this time (ISO 8601)
limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/tickets?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "0f1e2d3c-4b5a-4968-8776-655443322110",
      "object": "ticket",
      "number": 1042,
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "title": "Replace damaged grinder burr",
      "description": "Customer received a cracked burr with order #4417.",
      "type": "customer",
      "status": "in_progress",
      "priority": "high",
      "assignee": {
        "id": "usr_nora",
        "name": "Nora Patel"
      },
      "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "created_by": "Nora Patel",
      "created_at": "2026-10-04T18:25:00.000Z",
      "updated_at": "2026-10-04T18:40:12.000Z",
      "resolved_at": null
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Get a ticket

GET/api/v1/tickets/{id}inbox:read

Request
curl "https://www.chatrevia.com/api/v1/tickets/0f1e2d3c-4b5a-4968-8776-655443322110" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "id": "0f1e2d3c-4b5a-4968-8776-655443322110",
    "object": "ticket",
    "number": 1042,
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "title": "Replace damaged grinder burr",
    "description": "Customer received a cracked burr with order #4417.",
    "type": "customer",
    "status": "in_progress",
    "priority": "high",
    "assignee": {
      "id": "usr_nora",
      "name": "Nora Patel"
    },
    "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "created_by": "Nora Patel",
    "created_at": "2026-10-04T18:25:00.000Z",
    "updated_at": "2026-10-04T18:40:12.000Z",
    "resolved_at": null
  }
}

Create a ticket

POST/api/v1/ticketsinbox:write

A customer ticket linked to a conversation tells the visitor there and keeps them updated.

website_iduuid
Required when the key can use several websites (taken from the conversation when given)
titlestringrequired
descriptionstring
type"customer" | "back_office"
priority"low" | "normal" | "high" | "urgent"
conversation_iduuid
assignee_idstring
Request
curl -X POST "https://www.chatrevia.com/api/v1/tickets" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "title": "Replace damaged grinder burr",
       "priority": "high",
       "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41"
     }'
Response · 201
{
  "data": {
    "id": "0f1e2d3c-4b5a-4968-8776-655443322110",
    "object": "ticket",
    "number": 1042,
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "title": "Replace damaged grinder burr",
    "description": "Customer received a cracked burr with order #4417.",
    "type": "customer",
    "status": "in_progress",
    "priority": "high",
    "assignee": {
      "id": "usr_nora",
      "name": "Nora Patel"
    },
    "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "created_by": "Nora Patel",
    "created_at": "2026-10-04T18:25:00.000Z",
    "updated_at": "2026-10-04T18:40:12.000Z",
    "resolved_at": null
  }
}

Update a ticket

PATCH/api/v1/tickets/{id}inbox:write

Change status, priority, assignee, title or description. Status changes on customer tickets are posted to the linked conversation.

status"submitted" | "in_progress" | "waiting" | "resolved"
priority"low" | "normal" | "high" | "urgent"
assignee_idstring | null
titlestring
descriptionstring
Request
curl -X PATCH "https://www.chatrevia.com/api/v1/tickets/0f1e2d3c-4b5a-4968-8776-655443322110" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "status": "in_progress",
       "assignee_id": "usr_nora"
     }'
Response · 200
{
  "data": {
    "id": "0f1e2d3c-4b5a-4968-8776-655443322110",
    "object": "ticket",
    "number": 1042,
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "title": "Replace damaged grinder burr",
    "description": "Customer received a cracked burr with order #4417.",
    "type": "customer",
    "status": "in_progress",
    "priority": "high",
    "assignee": {
      "id": "usr_nora",
      "name": "Nora Patel"
    },
    "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
    "created_by": "Nora Patel",
    "created_at": "2026-10-04T18:25:00.000Z",
    "updated_at": "2026-10-04T18:40:12.000Z",
    "resolved_at": null
  }
}

Knowledge

List Q&A snippets

GET/api/v1/knowledge/snippetsknowledge:read

Written answers the AI agent learns from, newest first.

website_iduuid
Only this website. Default: every website the key can use
status"published" | "draft" | "archived"
limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/knowledge/snippets?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b",
      "object": "snippet",
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "question": "Do you ship internationally?",
      "answer": "Yes. We ship to the US, Canada, the UK and the EU in 5 to 9 business days.",
      "status": "published",
      "created_at": "2026-10-04T18:40:00.000Z",
      "updated_at": "2026-10-04T18:40:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Create a Q&A snippet

POST/api/v1/knowledge/snippetsknowledge:write

Published snippets are indexed at once and the AI agent can use them in its next answer; drafts wait for review in Knowledge. Needs a key that acts as an administrator.

website_iduuid
Required when the key can use several websites
questionstringrequired
answerstringrequired
status"published" | "draft"
Request
curl -X POST "https://www.chatrevia.com/api/v1/knowledge/snippets" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "question": "Do you ship internationally?",
       "answer": "Yes. We ship to the US, Canada, the UK and the EU in 5 to 9 business days."
     }'
Response · 201
{
  "data": {
    "id": "4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b",
    "object": "snippet",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "question": "Do you ship internationally?",
    "answer": "Yes. We ship to the US, Canada, the UK and the EU in 5 to 9 business days.",
    "status": "published",
    "created_at": "2026-10-04T18:40:00.000Z",
    "updated_at": "2026-10-04T18:40:00.000Z"
  }
}

Update a Q&A snippet

PATCH/api/v1/knowledge/snippets/{id}knowledge:write

Changes only the fields you send; a published snippet stays published unless you set status. The previous text is kept in its version history.

questionstring
answerstring
status"published" | "draft"
Request
curl -X PATCH "https://www.chatrevia.com/api/v1/knowledge/snippets/4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "status": "published"
     }'
Response · 200
{
  "data": {
    "id": "4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b",
    "object": "snippet",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "question": "Do you ship internationally?",
    "answer": "Yes. We ship to the US, Canada, the UK and the EU in 5 to 9 business days.",
    "status": "published",
    "created_at": "2026-10-04T18:40:00.000Z",
    "updated_at": "2026-10-04T18:40:00.000Z"
  }
}

Delete a Q&A snippet

DELETE/api/v1/knowledge/snippets/{id}knowledge:write

Request
curl -X DELETE "https://www.chatrevia.com/api/v1/knowledge/snippets/4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "id": "4e2d1c0b-9a8f-4e7d-8c6b-5a4f3e2d1c0b",
    "object": "snippet",
    "deleted": true
  }
}

Orders

Record an order

POST/api/v1/ordersorders:write

Reports an order from your backend for revenue attribution: Chatrevia attributes it to the conversation that led to it (the conversation_id you send, the buyer's email or phone, a chat discount code, a product added from chat) within the website's attribution window, and sends order.attributed. Idempotent on order_id: reporting the same order again returns it unchanged (200). It replaces an unattributed copy reported by the purchase snippet. Shopify orders arrive on their own. Needs a plan with commerce features.

website_iduuid
order_idstring | integerrequired
Your order ID; reporting it again changes nothing
namestring
Shown in reports, e.g. #1042
totalnumberrequired
Order total in its currency
subtotalnumber
currencystringrequired
itemsarray of object
discount_codesarray of string
emailstring
The buyer's email (attribution by email)
phonestring
customer_namestring
placed_atISO 8601 time
When it was placed (default: now); up to 400 days ago
conversation_iduuid
The conversation that led to it, when your checkout knows it
Request
curl -X POST "https://www.chatrevia.com/api/v1/orders" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "order_id": "1042",
       "total": 46.5,
       "currency": "USD",
       "email": "maya.chen@example.com",
       "items": [
         {
           "id": "NW-ETH-GUJI-12",
           "name": "Ethiopia Guji Natural · 12 oz",
           "quantity": 2,
           "price": 19
         }
       ],
       "discount_codes": [
         "NORA-7XK2QP"
       ]
     }'
Response · 201
{
  "data": {
    "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
    "object": "order",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "platform": "shopify",
    "source": "shopify",
    "order_id": "5512044331",
    "name": "#1042",
    "total": 46.5,
    "subtotal": 51.5,
    "currency": "USD",
    "items": [
      {
        "id": "NW-ETH-GUJI-12",
        "variant_id": "44012345678",
        "product_id": "8123456789",
        "name": "Ethiopia Guji Natural · 12 oz",
        "quantity": 2,
        "price": 19
      },
      {
        "id": "NW-FLT-V60",
        "variant_id": "44012345990",
        "product_id": "8123456990",
        "name": "Hario V60 Paper Filters",
        "quantity": 1,
        "price": 13.5
      }
    ],
    "discount_codes": [
      "NORA-7XK2QP"
    ],
    "email": "maya.chen@example.com",
    "placed_at": "2026-10-04T19:02:44.000Z",
    "attribution": {
      "type": "direct",
      "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "channel": "web",
      "handled_by": "ai",
      "reasons": [
        "discount",
        "conversation"
      ],
      "last_chat_at": "2026-10-04T18:21:09.000Z",
      "window_days": 7
    },
    "created_at": "2026-10-04T19:02:46.000Z"
  }
}

List orders

GET/api/v1/ordersorders:read

Orders reported by Shopify, the purchase snippet and the API, newest first, with their attribution.

website_iduuid
Only this website. Default: every website the key can use
attribution"direct" | "influenced" | "recovered" | "none" | "any"
any: attributed to a conversation (direct, influenced or recovered from an abandoned cart)
conversation_iduuid
placed_afterISO 8601 time
Only records placed after this time (ISO 8601)
limitinteger
Results per page, 1 to 100 (default 25)
cursorstring
next_cursor from the previous page
Request
curl "https://www.chatrevia.com/api/v1/orders?limit=10" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
      "object": "order",
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "platform": "shopify",
      "source": "shopify",
      "order_id": "5512044331",
      "name": "#1042",
      "total": 46.5,
      "subtotal": 51.5,
      "currency": "USD",
      "items": [
        {
          "id": "NW-ETH-GUJI-12",
          "variant_id": "44012345678",
          "product_id": "8123456789",
          "name": "Ethiopia Guji Natural · 12 oz",
          "quantity": 2,
          "price": 19
        },
        {
          "id": "NW-FLT-V60",
          "variant_id": "44012345990",
          "product_id": "8123456990",
          "name": "Hario V60 Paper Filters",
          "quantity": 1,
          "price": 13.5
        }
      ],
      "discount_codes": [
        "NORA-7XK2QP"
      ],
      "email": "maya.chen@example.com",
      "placed_at": "2026-10-04T19:02:44.000Z",
      "attribution": {
        "type": "direct",
        "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
        "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
        "channel": "web",
        "handled_by": "ai",
        "reasons": [
          "discount",
          "conversation"
        ],
        "last_chat_at": "2026-10-04T18:21:09.000Z",
        "window_days": 7
      },
      "created_at": "2026-10-04T19:02:46.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "WyIyMDI2LTEwLTA0IDE4OjIwOjUxLjAwMCIsIjhkMGM1ZjhlIl0"
}

Get an order

GET/api/v1/orders/{id}orders:read

Request
curl "https://www.chatrevia.com/api/v1/orders/2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
    "object": "order",
    "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
    "platform": "shopify",
    "source": "shopify",
    "order_id": "5512044331",
    "name": "#1042",
    "total": 46.5,
    "subtotal": 51.5,
    "currency": "USD",
    "items": [
      {
        "id": "NW-ETH-GUJI-12",
        "variant_id": "44012345678",
        "product_id": "8123456789",
        "name": "Ethiopia Guji Natural · 12 oz",
        "quantity": 2,
        "price": 19
      },
      {
        "id": "NW-FLT-V60",
        "variant_id": "44012345990",
        "product_id": "8123456990",
        "name": "Hario V60 Paper Filters",
        "quantity": 1,
        "price": 13.5
      }
    ],
    "discount_codes": [
      "NORA-7XK2QP"
    ],
    "email": "maya.chen@example.com",
    "placed_at": "2026-10-04T19:02:44.000Z",
    "attribution": {
      "type": "direct",
      "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "channel": "web",
      "handled_by": "ai",
      "reasons": [
        "discount",
        "conversation"
      ],
      "last_chat_at": "2026-10-04T18:21:09.000Z",
      "window_days": 7
    },
    "created_at": "2026-10-04T19:02:46.000Z"
  }
}

Workspace

Check your key

GET/api/v1/me

The key's workspace, scopes and websites. A quick way to test authentication.

Request
curl "https://www.chatrevia.com/api/v1/me" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY"
Response · 200
{
  "data": {
    "object": "api_key",
    "id": "3f2e1d0c-…",
    "name": "Order system",
    "scopes": [
      "inbox:write",
      "people:write",
      "knowledge:read"
    ],
    "role": "admin",
    "workspace": {
      "id": "1a2b3c4d-…",
      "name": "Northwind Coffee",
      "plan": "pro"
    },
    "websites": [
      {
        "id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
        "name": "Northwind Coffee",
        "url": "https://northwindcoffee.com"
      }
    ]
  }
}

Webhooks

Add an endpoint in Settings → Developers → Webhooks and pick its events. Chatrevia sends a POST with this JSON body the moment the change is saved. Any 2xx response within 10 seconds counts as delivered.

EventWhen
conversation.createdA visitor sent the first message in a conversation (data.message is that message).
message.createdA visitor, the AI agent or a teammate sent a message (data.message.author.type is visitor, ai or teammate).
conversation.assignedA conversation was assigned to a teammate.
conversation.closedA conversation was resolved.
handoff.requestedA visitor asked to talk to a person.
conversation.escalatedA conversation was sent to your helpdesk (Zendesk, Gorgias or Freshdesk) and the ticket was created. data.escalation.external_ticket has its id and link.
csat.submittedA visitor rated a resolved conversation (1 to 5).
contact.identifiedYour website identified a signed-in user in the messenger (identify). data.verified says whether identity verification passed.
lead.capturedA visitor shared their contact details with consent.
ticket.createdA ticket was created by a teammate, an automation or the API.
ticket.updatedA ticket's status, priority, assignee, title or description changed. data.previous holds the old values.
action.runThe AI agent ran one of your AI actions (succeeded, failed or blocked).
discount.issuedThe AI agent gave a shopper a single-use Shopify discount code (value and rules from your discount settings).
return.requestedA shopper submitted a return or exchange in the messenger: a Shopify return request, or a ticket when Shopify couldn't take it.
order.attributedAn order (Shopify, the purchase snippet or the API) was attributed to a conversation: direct (a product added from chat, a chat discount code, checkout from the messenger), influenced (the buyer chatted within the attribution window) or recovered (it recovered an abandoned cart).
cart.abandonedA shopper's cart sat untouched past your "abandoned after" time and cart recovery started (Recovery settings). data.cart has its items and total.
cart.recoveredAn order recovered an abandoned cart: it came through the cart-restore link, or the shopper bought that cart after a reminder. data.order is the order.

Signatures

Every request has a Chatrevia-Signature header: t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of t + "." + raw body with the endpoint’s signing secret. Compare in constant time and reject timestamps older than 5 minutes. After you roll a secret, both the new and the old signature are sent until the old one expires.

Retries

Failed deliveries are retried 5 times, after about 1 min, 10 min, 1 h, 6 h, 16 h (6 attempts over about a day). Each attempt, its status, latency and response are in the delivery log, where you can resend any delivery or send a test event. An endpoint that fails for 3 days is turned off and your administrators are told. Events can arrive out of order; use created_at and the event id to order and de-duplicate.

conversation.closed
{
  "id": "evt_3f9c2a7d1b8e4f60a1c5d7e9b2f4a6c8",
  "type": "conversation.closed",
  "created_at": "2026-10-04T18:32:40.000Z",
  "workspace_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "data": {
    "conversation": {
      "id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41",
      "object": "conversation",
      "website_id": "5b8e1c2a-7d34-4f0b-8e6a-1c9d2f3a4b5c",
      "status": "closed",
      "channel": "web",
      "visitor": {
        "name": "Maya Chen",
        "email": "maya.chen@example.com",
        "user_id": "cus_48213",
        "verified": true
      },
      "contact_id": "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "assignee": null,
      "taken_over": false,
      "priority": "normal",
      "tags": [
        "orders"
      ],
      "summary": "Where is my order #4417?",
      "handoff_requested_at": null,
      "snoozed_until": null,
      "csat": null,
      "last_visitor_message_at": "2026-10-04T18:21:07.000Z",
      "closed_at": "2026-10-04T18:32:40.000Z",
      "created_at": "2026-10-04T18:20:51.000Z",
      "updated_at": "2026-10-04T18:21:07.000Z"
    }
  }
}
Verify the signature
import crypto from "node:crypto";
import express from "express";

const app = express();
// The raw body: verify exactly the bytes Chatrevia signed.
app.post("/chatrevia", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("Chatrevia-Signature") || "";
  const t = header.match(/t=(\d+)/)?.[1];
  const sent = [...header.matchAll(/v1=([0-9a-f]{64})/g)].map((m) => m[1]);
  const expected = crypto
    .createHmac("sha256", process.env.CHATREVIA_WEBHOOK_SECRET)
    .update(`${t}.${req.body}`)
    .digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  const valid = sent.some((s) =>
    crypto.timingSafeEqual(Buffer.from(s, "hex"), Buffer.from(expected, "hex")),
  );
  if (!t || !fresh || !valid) return res.sendStatus(400);
  const event = JSON.parse(req.body);
  // Handle event.type (e.g. "conversation.closed"), then answer quickly.
  res.sendStatus(200);
});

Zapier, Make & n8n

There’s no app to install: webhooks and the REST API work with any automation tool. To send new conversations to a Google Sheet or a Slack channel with Zapier:

  1. In Zapier, create a Zap with the trigger Webhooks by Zapier → Catch Hook and copy its URL.
  2. In Chatrevia, open Settings → Developers → Webhooks, choose Add endpoint, paste the URL and pick events such as conversation.created and lead.captured.
  3. Open the endpoint and choose Send test event. Back in Zapier, click Test trigger: the sample event appears, with fields like data__conversation__visitor__email.
  4. Add your action (Google Sheets, Slack, HubSpot…) and map the fields. To act back in Chatrevia, add a Webhooks by Zapier → Custom Request step that calls the REST API with your key, for example to create a ticket.

In Make, use the Webhooks → Custom webhook module; in n8n, the Webhook node with method POST. Check the signature in a code step when the flow changes data.

Create a ticket from a Zap
curl -X POST "https://www.chatrevia.com/api/v1/tickets" \
  -H "Authorization: Bearer $CHATREVIA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
       "title": "Replace damaged grinder burr",
       "priority": "high",
       "conversation_id": "8d0c5f8e-2f6b-4c1e-9a52-3f1d7b9e6a41"
     }'

Identity verification

When a customer is signed in to your website, tell the messenger who they are with Chatrevia.identify(). To prove it, your server signs the user with the website’s identity secret (Settings → Developers → Identity verification):

  • User hash: HMAC-SHA256 of the user ID, as hex. The user ID is verified; name and email are taken as given.
  • JWT: an HS256 token with sub (your user ID), exp (at most 24 hours ahead), and optionally email, name and attributes. Its email counts as verified, so order lookup won’t ask for it.

Verified visitors are linked to one person per user ID, marked Verified in the inbox and People, and announced with a contact.identified webhook. With Require verification on, an unsigned identify() can’t set a name or email or link to anyone. Never put the secret in your page.

On your server: user hash
import crypto from "node:crypto";

// On your server, for the signed-in user. Never put the secret in the page.
const userHash = crypto
  .createHmac("sha256", process.env.CHATREVIA_IDENTITY_SECRET)
  .update(String(user.id))
  .digest("hex");
In your page
<script>
  // After the Chatrevia embed, on pages where the user is signed in.
  Chatrevia.identify({
    userId: "{{ user.id }}",
    email: "{{ user.email }}",
    name: "{{ user.name }}",
    userHash: "{{ user_hash }}"   // from your server
  });
</script>
Or a JWT
import jwt from "jsonwebtoken";

const token = jwt.sign(
  { sub: String(user.id), email: user.email, name: user.name },
  process.env.CHATREVIA_IDENTITY_SECRET,
  { algorithm: "HS256", expiresIn: "1h" },
);

Connect Chatrevia to the rest of your stack.

Start free, then add the REST API and webhooks on Pro when you’re ready to automate.

Get started free