Skip to content
Reference

REST API

Everything you can do in the dashboard, over HTTP. Read conversations into your own tools, reply as your team, keep knowledge in sync with your product, and tune agents from code.

Basics

  • Base URL: https://api.recursivechat.dev
  • JSON in and out, over HTTPS only.
  • Most requests need your workspaceId, and requests about one website, agent or conversation also need its siteId. IDs are shown in the dashboard and returned by the API.
terminal
curl "https://api.recursivechat.dev/v1/conversations?workspaceId=ws_123&status=needs_human" \
  -H "Authorization: Bearer rc_sk_your_secret_key"

API keys and scopes

Create keys in the dashboard under API. A key is shown once, starts with rc_sk_, and is sent as a Bearer token. Store it on your server; never put it in a web page or app.

Give each key only what it needs. Scopes come in read and write pairs:

ScopeCovers
conversations:readList and read conversations and messages, export transcripts.
conversations:writeReply as the team, add notes, take over, close, reopen, assign, mark read.
agents:read / writeRead, create, update and delete agents; test an agent.
knowledge:read / writeRead, add, refresh and delete knowledge sources.
sites:read / writeRead, add, update and delete websites.
visitors:read / writeRead visitors and their page views; set tags.
members:read / writeRead the team, invite, change roles and remove people.
usage:readRead this month’s usage.

A key can also be limited to some of your websites. Keys can never create or delete other keys: that needs a signed in person in the dashboard.

Requests, responses and errors

Successful responses wrap the result in data. Errors return an error object with a stable code, a readable message and a requestId to quote if you contact us.

200 OK
{
  "data": {
    "conversations": [
      {
        "conversation": { "id": "conv_…", "status": "open", "mode": "ai", "needsHuman": true, … },
        "visitor": { "id": "vis_…", "email": "sam@example.com", "metadata": { "plan": "Pro" }, … }
      }
    ]
  }
}
403 Forbidden
{
  "error": {
    "code": "forbidden",
    "message": "API key is missing the conversations:write scope",
    "requestId": "req_…"
  }
}
StatusCodeMeaning
401unauthenticatedMissing or invalid key.
403forbiddenThe key lacks a scope or access to that website.
404not_foundNo such item, or it belongs to another workspace.
409conflictNot possible in the current state, such as replying to a closed conversation.
413payload_too_largeThe upload or text is too big.
422validation_failedA field is missing or wrong. The message says which.
429rate_limitedToo many requests. Wait and retry with backoff.
500internalSomething went wrong on our side.

Conversations

List and detail requests take workspaceId and siteId as query parameters. Actions take them in the JSON body.

  • GET/v1/conversationsconversations:read
    List conversations, newest first. Query: status (open, needs_human, closed or all), siteId, limit up to 100.
  • GET/v1/conversations/:idconversations:read
    One conversation with its visitor.
  • GET/v1/conversations/:id/messagesconversations:read
    The messages, including internal notes.
  • GET/v1/conversations/:id/exportconversations:read
    Transcript download. Query: format (json or csv), anonymize (true or false).
  • POST/v1/conversations/:id/messagesconversations:write
    Reply as the team. Body: content. Replying takes the conversation over from the AI and clears Needs you.
  • POST/v1/conversations/:id/notesconversations:write
    Internal note the visitor never sees. Body: content.
  • POST/v1/conversations/:id/handoffconversations:write
    Body: action (takeover stops the AI, return hands back to it).
  • POST/v1/conversations/:id/closeconversations:write
    Close the conversation.
  • POST/v1/conversations/:id/reopenconversations:write
    Reopen it.
  • POST/v1/conversations/:id/assignconversations:write
    Body: assigneeUid, or null to unassign.
  • POST/v1/conversations/:id/readconversations:write
    Mark it read by the team.
Reply as your team
curl -X POST "https://api.recursivechat.dev/v1/conversations/conv_123/messages" \
  -H "Authorization: Bearer rc_sk_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "ws_123",
    "siteId": "site_123",
    "content": "Thanks for waiting. I have refreshed your account, please try again."
  }'

Agents

Agent requests take workspaceId and siteId as query parameters. The fields match the agent's Settings in the dashboard.

  • GET/v1/agentsagents:read
    List agents. Query: siteId to filter.
  • POST/v1/agentsagents:write
    Create an agent. Body: siteId, name, and any settings below.
  • GET/v1/agents/:agentIdagents:read
    Read an agent.
  • PATCH/v1/agents/:agentIdagents:write
    Update settings. Send only the fields you change.
  • DELETE/v1/agents/:agentIdagents:write
    Switch an agent off. It stops answering and no longer appears on your site.
  • POST/v1/agents/:agentId/chatagents:read
    Test the agent without starting a real conversation. Body: message, optional history.
FieldType
instructionsText, 10 to 8,000 characters.
tonefriendly, professional or concise.
languageauto to reply in the visitor's language, or a language code such as en.
welcomeMessageFirst message shown in the chat.
fallbackMessageWhat the AI may say when it cannot help.
humanHandoffEnabledtrue or false.
handoffStylesolve_first or offer_early.
replyTimeText such as "within one working day", or null.
teamHoursSet hours: days (0 Sunday to 6 Saturday), start and end as 24 hour HH:MM, and an IANA timeZone such as Europe/London. Or null.
supportHoursHours in your own words, used only when teamHours is null.
aiContextFieldsVisitor metadata keys the AI may see, up to 25.
aiSeesCurrentPagetrue or false.
requireEmailAsk for an email in the chat after the first message.
statusactive or disabled.
appearanceColours, position, launcher style, header text and more. Send only the fields you change.
Update handover settings
curl -X PATCH "https://api.recursivechat.dev/v1/agents/agent_123?workspaceId=ws_123&siteId=site_123" \
  -H "Authorization: Bearer rc_sk_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "handoffStyle": "solve_first",
    "replyTime": "within one working day",
    "teamHours": {
      "days": [1, 2, 3, 4, 5],
      "start": "09:00",
      "end": "17:00",
      "timeZone": "Europe/London"
    },
    "aiContextFields": ["plan"]
  }'

Knowledge

Knowledge requests take workspaceId and siteId as query parameters. New and refreshed sources are read in the background: check status until it is ready. For a web page, mediaCount says how many same-site images and videos were kept with its passages. When the AI answers from one of those passages, its message can carry a media list (each with kind image or video, src, poster and alt), which the widget shows as cards.

  • GET/v1/agents/:agentId/sourcesknowledge:read
    List sources with their status.
  • POST/v1/agents/:agentId/sourcesknowledge:write
    Add a source. Body: type url with url, or type text with title and text (up to 200,000 characters).
  • GET/v1/agents/:agentId/sources/:sourceIdknowledge:read
    One source.
  • GET/v1/agents/:agentId/sources/:sourceId/chunksknowledge:read
    The passages the AI searches, to check what it has read.
  • POST/v1/agents/:agentId/sources/:sourceId/syncknowledge:write
    Read the source again, for example after the page changed.
  • DELETE/v1/agents/:agentId/sources/:sourceIdknowledge:write
    Remove a source.
Push your product guide from CI
curl -X POST "https://api.recursivechat.dev/v1/agents/agent_123/sources?workspaceId=ws_123&siteId=site_123" \
  -H "Authorization: Bearer rc_sk_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "title": "Product guide",
    "text": "# Getting started\n..."
  }'

Websites

  • GET/v1/sitessites:read
    List websites, with their widget IDs.
  • POST/v1/sitessites:write
    Add a website.
  • GET/v1/sites/:siteIdsites:read
    One website.
  • PATCH/v1/sites/:siteIdsites:write
    Update a website.
  • DELETE/v1/sites/:siteIdsites:write
    Remove a website. Its chat stops working.

Visitors

Visitor requests take workspaceId and siteId as query parameters.

  • GET/v1/visitors/:idvisitors:read
    A visitor, with location, browser, metadata and tags.
  • GET/v1/visitors/:id/pageviewsvisitors:read
    Pages they have visited.
  • GET/v1/visitors/:id/conversationsvisitors:read
    Their conversations.
  • PATCH/v1/visitors/:id/tagsvisitors:write
    Replace their tags. Body: workspaceId, siteId, tags (up to 20).

Team and usage

  • GET/v1/membersmembers:read
    Your team and their roles.
  • PATCH/v1/members/:uidmembers:write
    Change a role or which websites someone can see.
  • DELETE/v1/members/:uidmembers:write
    Remove someone.
  • GET/v1/invitationsmembers:read
    Pending invitations.
  • POST/v1/invitationsmembers:write
    Invite someone by email.
  • DELETE/v1/invitations/:invitationIdmembers:write
    Cancel an invitation.
  • GET/v1/usageusage:read
    This month’s AI replies and other usage.