Connect Crisp to Fondoo

Live5 min readUpdated

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. cursor is the Crisp page number; limit is clamped to Crisp's page size range 20..50 (a limit below 20 still returns up to 20). next_page is set whenever Crisp returned a full page. Crisp has no priority, so every ticket reports normal; tags are the conversation segments; subject is the meta subject, else the generated topic, else the last-message excerpt.
  • tickets.get (read): the conversation plus its message history; description is the first customer text message, requester comes from the conversation meta email/nickname, assignee_id is the routed operator user ID.
  • tickets.comments (read): every message in the conversation, oldest first, walking timestamp_before batches until Crisp returns an empty batch (at most 8 batches per call). If that cap is reached, or a batch makes no progress, next_page is the timestamp to continue from and core treats the thread as partial (human review). Notes are public:false; customer messages are customer, operator messages agent, automated operator messages bot; system event messages 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 a from:'user' message with origin:'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'} using origin:'email' when the conversation meta origin is email and chat otherwise (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_id must 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 stateFondoo status (read)
pendingnew
unresolvedopen
resolvedsolved
Fondoo status (write)Crisp state
newpending
openunresolved
pendingunresolved (Crisp has no waiting-on-customer state)
solved, closedresolved (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

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 signs JSON.stringify of 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 segments in 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 limit under 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.