Use DeskClerk AI answers behind Facebook Messenger
1. Who this page is for
You run a Facebook Page with Messenger, and want your own page backend to get AI answers from DeskClerk before a human picks up.
2. What you get, and what you do not get
You get
- The same AI answers that run on your website, exposed as two simple HTTPS endpoints your own code can call.
- Conversation memory: keep one
conversationIdper Messenger thread and the AI remembers what was said before. - A handoff signal the platform computes for you: the reply carries an
escalationobject when a human should take over, so you do not have to write detection rules. - One API for every channel. Adding Messenger does not change your DeskClerk setup.
You do not get
- We do not run inside Messenger. There is no Messenger app, bot, or connector from us, and no marketplace listing.
- We do not receive or send Messenger messages. Your own backend (or the platform you use for that channel) keeps doing that job.
- We do not know your channel's user IDs. You pass your own
external_user_id, which only has to be stable on your side. - Usage counts against your plan's monthly quota, per answered message. When you need more, you can top up at any time.
3. Before you start
- A DeskClerk site that has been published at least once. Without a publish the AI has nothing to answer from.
- Your Site ID (a UUID, for example
7b0c9f5e-2a8d-4f31-8e6b-1c2d3e4f5a6b). It is shown in your workspace under the site settings. - An API key with the
chat:writescope. Create it in your workspace and keep it on your server only — never in a mobile app or in front-end JavaScript. - A server that can call HTTPS endpoints, plus a place to store one
conversationIdper user thread. - The language code you will send as
locale. It has to be one of the languages enabled for your site (for exampleenorzh), written exactly as your site settings show it. - Your Messenger messaging backend. Sending and receiving messages in Messenger stays on your side; DeskClerk is the answering engine you call.
4. Step by step
- Keep your Meta app and webhook receiver. DeskClerk does not listen to Messenger events.
- Map each Messenger conversation (PSID) to one DeskClerk
conversationIdand store the mapping. - Post each inbound text to the message endpoint and send
aiMessage.contentback through the Send API. - When the response is missing
aiMessage, or carriesescalation, hand the thread to a human agent instead of replying. - Reuse the stored
conversationIdfor the rest of the thread.
The two steps below are the whole integration: create a conversation, then post each message. Nothing else is required, and the API only ever grows — what you write today keeps working.
5. Copy-paste example
Set these three values once, then the rest is boilerplate:
| Variable | Example value | Where it comes from |
|---|---|---|
BASE_URL |
https://chat.example.com |
The host that serves your widget and help center |
SITE_ID |
7b0c9f5e-2a8d-4f31-8e6b-1c2d3e4f5a6b |
Workspace → site settings |
DESKCLERK_API_KEY |
your key | Workspace → API keys (chat:write scope) |
Step 1 — create the conversation (once per thread):
curl -sS -X POST "$BASE_URL/api/v1/integrations/sites/$SITE_ID/conversations" \
-H "X-Integration-Api-Key: $DESKCLERK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: conv-messenger-12025550123-1" \
-d '{"channel":"messenger","external_user_id":"12025550123","user_name":"Sam","locale":"en","timezone":"America/New_York"}'
The response contains data.id — that is your conversationId. Store it next to your own thread ID. The example UUID for a stored conversation is 0f4c2a91-5d63-4b8e-9f27-3a1b6c8d5e40.
Step 2 — send each message and show the answer:
curl -sS -X POST "$BASE_URL/api/v1/integrations/sites/$SITE_ID/conversations/$CONVERSATION_ID/messages" \
-H "X-Integration-Api-Key: $DESKCLERK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: msg-messenger-12025550123-1" \
-d '{"content":"Do you ship to Canada?"}'
A complete Node.js handler, including both branches you must handle:
const BASE_URL = "https://chat.example.com";
const SITE_ID = "7b0c9f5e-2a8d-4f31-8e6b-1c2d3e4f5a6b";
const API_KEY = process.env.DESKCLERK_API_KEY;
async function reply(channel, externalUserId, locale, text) {
const convRes = await fetch(`${BASE_URL}/api/v1/integrations/sites/${SITE_ID}/conversations`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Integration-Api-Key": API_KEY,
"Idempotency-Key": `conv-${channel}-${externalUserId}-${Date.now()}`
},
body: JSON.stringify({
channel,
external_user_id: externalUserId,
locale,
timezone: "America/New_York"
})
});
const conv = await convRes.json();
if (conv.code !== 0) {
throw new Error(`create conversation failed: ${conv.code} ${conv.message}`);
}
const conversationId = conv.data.id;
const msgRes = await fetch(
`${BASE_URL}/api/v1/integrations/sites/${SITE_ID}/conversations/${conversationId}/messages`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Integration-Api-Key": API_KEY,
"Idempotency-Key": `msg-${conversationId}-${Date.now()}`
},
body: JSON.stringify({ content: text })
}
);
const msg = await msgRes.json();
if (msg.code !== 0) {
throw new Error(`send message failed: ${msg.code} ${msg.message}`);
}
// No AI answer this turn: hand the thread to a human on your side.
if (!msg.data.aiMessage) {
return { conversationId, text: "A teammate will reply here shortly.", escalate: true };
}
// The platform decides when a human should take over.
const escalate = Boolean(msg.data.escalation);
return { conversationId, text: msg.data.aiMessage.content, escalate };
}
reply("messenger", "12025550123", "en", "Do you ship to Canada?").then(console.log);
Each message call is synchronous and can take up to 45 seconds, so give your HTTP client a timeout above that. If you need to show words as they arrive, use the streaming twin endpoint .../messages/stream instead; the request body is the same.
6. Common questions
-
I get
403 Forbidden/code 40301. The key is missing, disabled, or does not carry the scope the endpoint needs. Check that the header name is exactlyX-Integration-Api-Key(orAuthorization: Bearer <key>), that the key isACTIVE, and that this Site ID is listed on the key. -
I get
429 Too Many Requests/code 42901. You are above the request rate for the site. Read theRetry-Afterheader, wait that many seconds, then retry with backoff. Do not retry in a tight loop. -
The bubble does not appear on the page. View the page source and search for
widget.js— if it is missing, the snippet is not on the rendered page (a cache plugin or a theme setting is dropping it). If it is present, check the browser console for a Content-Security-Policy error and allowhttps://chat.example.cominscript-srcandconnect-src. Ad blockers also hide chat bubbles; test in a clean profile. -
The bubble appears but the answer says it does not know. The knowledge is empty, still processing, or tagged with a different locale. In your workspace open Site → Knowledge and confirm the item count is above zero, the pending count is zero, and the item locale matches how visitors ask.
-
Creating a conversation returns
400withLocale must be enabled for this site's Help Center.localemust be one of the language codes enabled for your site (for exampleenorzh) — not a region form such asen-USorzh-CN. Check the language list in your site settings and send the code exactly as it appears there. -
aiMessageisnullbut the call succeeded. That is not an error: it means the site's assistant did not answer this turn (for example the assistant is paused for that conversation). Show your own fallback text and route the thread to a human. -
I get
404on the message call. Almost always a wrongconversationId— it must be thedata.idyou stored, a UUID, not your own thread ID. A malformed Site ID returns the same status. -
What is
sources[].score? A retrieval similarity between 0 and 1, useful for a "show the reference" UI. It is not an accuracy score. -
Should I send the conversation history again? No. Send only the new message; the platform keeps the context for the
conversationId.
7. Who to contact
- Product and setup questions:
[email protected] - Include in every message: your Site ID, the exact request (method and path), the HTTP status, the
codefrom the response body, and theIdempotency-Keyyou used. That is everything we need to find the request in our logs. - Security: never send us your API key in plain text. The key prefix (the first characters) is enough for us to locate it.