Connect Crisp to Fondoo
Crisp in Fondoo: what your AI agent can do with it, what to set up first, the permissions it needs and its limits.
Crisp requires a plugin token: in the Crisp Marketplace create a private plugin, request a production token with the scopes website:conversation:sessions, website:conversation:messages, website:conversation:states, website:conversation:routing and website:conversation:initiate (read and write), install the plugin on your workspace, then paste the token identifier and key plus your website ID (a UUID). Production plugin tokens have a daily request quota (5,000 per day by default, raisable on request; the development token is much lower). For live updates add a Plugin Hook in the same plugin and paste its signing secret as webhookSecret; Website Hooks are unsigned and will be rejected.
Official documentation: https://docs.crisp.chat/references/rest-api/v1/
Use add_connection_key without fields for a signed, one-use secure paste page. Then call test_connection and inspect confirmed versus unknown permissions. Direct tool credentials carry a chat-log warning. list_connections never returns credentials.
Auth: api_key (HTTP Basic identifier:key plus X-Crisp-Tier: plugin). Category: support. Required provider scopes: website:conversation:sessions, website:conversation:messages, website:conversation:states, website:conversation:routing, website:conversation:initiate.
Credential fields: identifier and key (secret, the plugin token keypair), websiteId (not secret, UUID), webhookSecret (secret, optional, the Plugin Hook signing secret).
Capabilities are discoverable with list_connector_manifests; invoke them through connector_action. Writes retain shared Fondoo scopes, approvals, dry runs, audit, events and metering. Use rotate_connection_key before expiry and delete_connection to remove stored credentials; revoke upstream credentials separately.
What Fondoo does with Crisp
Crisp is a helpdesk provider for the M15 support switch: set_provider({siteId, capability:'support', provider:'crisp'}) routes the shared support ticket operations to this connection. A Fondoo "ticket" is a Crisp conversation and its ID is the Crisp session_id (session_<uuid>).
Normalized capabilities (all through connector_action or the support operations):
tickets.list(read): one page of conversations.cursoris the Crisp page number;limitis clamped to Crisp's page size range 20..50 (alimitbelow 20 still returns up to 20).next_pageis set whenever Crisp returned a full page. Crisp has no priority, so every ticket reportsnormal;tagsare the conversation segments;subjectis the meta subject, else the generated topic, else the last-message excerpt.tickets.get(read): the conversation plus its message history;descriptionis the first customer text message,requestercomes from the conversation meta email/nickname,assignee_idis the routed operator user ID.tickets.comments(read): every message in the conversation, oldest first, walkingtimestamp_beforebatches until Crisp returns an empty batch (at most 8 batches per call). If that cap is reached, or a batch makes no progress,next_pageis the timestamp to continue from and core treats the thread as partial (human review). Notes arepublic:false; customer messages arecustomer, operator messagesagent, automated operator messagesbot; systemeventmessages are omitted; files appear as[file: name].tickets.create(write): creates a conversation, sets meta (email, nickname, subject, segments), then posts the customer's text as afrom:'user'message withorigin:'email'(the conversation only becomes visible in the Crisp inbox after a user message). Three requests; if a later step fails, an empty, invisible conversation can remain in Crisp and the call fails.tickets.update(write): a reply (public:true) is posted as{type:'text', from:'operator'}usingorigin:'email'when the conversation meta origin is email andchatotherwise (one extra read to learn the origin); a note (public:false) is posted as{type:'note', from:'operator', origin:'chat'}, which Crisp keeps internal. Status, segments (tags, full desired set) and assignment (assignee_idmust be a Crisp operator user UUID) are separate PATCH requests. Priority writes are validated and ignored because Crisp has no priority.
Status mapping (Crisp pending|unresolved|resolved):
| Crisp state | Fondoo status (read) |
|---|---|
pending | new |
unresolved | open |
resolved | solved |
| Fondoo status (write) | Crisp state |
|---|---|
new | pending |
open | unresolved |
pending | unresolved (Crisp has no waiting-on-customer state) |
solved, closed | resolved (Crisp has no separate closed state) |
Because no Crisp state reads as pending or closed, tickets.list({status:'pending'|'closed'}) returns an empty list without calling Crisp. new lists unresolved-filtered conversations whose state is pending.
Webhooks: create a Plugin Hook in your Marketplace plugin pointing at the Fondoo support webhook URL and paste the hook secret into webhookSecret. Fondoo verifies X-Crisp-Signature as hex HMAC-SHA256, keyed with that secret, of the string [<X-Crisp-Request-Timestamp>;<body>] (raw body, and the official SDK's JSON.stringify(parsedBody) form), compares in constant time and rejects timestamps more than 5 minutes from now. session:request:initiated maps to a new conversation; message:send (visitor message), message:updated and session:set_state map to conversation updates; everything else, including message:received (operator messages, which would echo Fondoo's own replies), is ignored. The conversation ID is data.session_id. Website Hooks are not signed by Crisp, so they cannot pass verification.
API endpoints used
- Authentication (plugin token, Basic +
X-Crisp-Tier: plugin): https://docs.crisp.chat/guides/rest-api/authentication/plugin-token/ GET /v1/website/{website_id}/conversations/{page_number}(List Conversations,per_page,filter_resolved,filter_not_resolved): https://docs.crisp.chat/references/rest-api/v1/GET /v1/website/{website_id}/conversation/{session_id}(Get A Conversation): https://docs.crisp.chat/references/rest-api/v1/GET /v1/website/{website_id}/conversation/{session_id}/messages?timestamp_before=(Get Messages In Conversation): https://docs.crisp.chat/references/rest-api/v1/POST /v1/website/{website_id}/conversation(Create A New Conversation): https://docs.crisp.chat/references/rest-api/v1/POST /v1/website/{website_id}/conversation/{session_id}/message(Send A Message In Conversation,typetext/note,fromuser/operator,originchat/email): https://docs.crisp.chat/references/rest-api/v1/PATCH /v1/website/{website_id}/conversation/{session_id}/meta(Update Conversation Metas),/state(Change Conversation State),/routing(Assign Conversation Routing): https://docs.crisp.chat/references/rest-api/v1/- Web hooks, events and signature: https://docs.crisp.chat/references/web-hooks/v1/ and https://docs.crisp.chat/guides/web-hooks/plugin-hooks/
- Rate limits and quotas: https://docs.crisp.chat/guides/rest-api/rate-limits/ and https://docs.crisp.chat/guides/rest-api/authentication/
Limits and uncertainties
- Rate limit: plugin tokens are exempt from per-minute limits but have a daily quota (5,000/day by default per Crisp's authentication guide). Fondoo budgets 50 executes per hour because one execute can issue up to about 10 requests. Crisp answers 429 or 420 when limited.
- Uncertain: the signature digest encoding is not stated in the reference; hex is taken from the official Node SDK (
crisp-im/node-crisp-api,__verifySignature), which also signsJSON.stringifyof the parsed body rather than the raw bytes. The timestamp unit is not stated; example payloads use milliseconds and Fondoo accepts seconds too. - Uncertain: the reference does not say whether
segmentsin Update Conversation Metas replaces or merges. Fondoo sends the full desired set, which is correct under replace semantics; if Crisp merges, removed tags would remain. - Uncertain: the Create A New Conversation response body is not documented in the reference; Fondoo reads
data.session_id, as the official PHP example does, and fails closed if it is missing. - Uncertain: the Get Messages batch size and order are not documented, so Fondoo walks backwards until an empty batch instead of guessing a page size.
- Uncertain: whether an operator
origin:'email'message is delivered to the customer by email in every plan; Crisp's own email routing settings decide delivery. - A
limitunder 20 cannot be honoured exactly (Crisp's minimum page size is 20). - Session and operator IDs are validated as
session_<uuid>and UUID; other formats are rejected.
Compliance notes
Replies are sent to the customer by Crisp on the owner's behalf, and connected replies require owner approval in Fondoo. Notes are posted as Crisp note messages, which are internal to operators. Complaints, refunds and legal requests remain human-only through core routing. The connector has no delete, refund or payment capability. Webhook payloads are used only to learn the conversation ID; content is always re-read through the API.
