Integrations
Connect the Jamdesk Docs Search API to Intercom, Zendesk, Slack, and custom chatbots. Step-by-step guides for each integration.
The Docs Search API is designed to plug into the tools your team and customers already use. This guide covers the most common integrations.
Intercom (Fin AI Agent)
Intercom's Fin AI Agent supports Data Connectors — external search sources that Fin queries alongside your Intercom articles. Connect the Docs Search API so Fin can answer questions directly from your Jamdesk docs.
In the Jamdesk dashboard, go to Project Settings → API Keys and click Generate Key. Name it "Intercom Fin" and copy the jd_live_ key (40 chars total).
In Intercom, go to AI Agent → Data Sources → Add Source → API.
Enter the following details:
| Field | Value |
|---|---|
| Endpoint URL | https://your-project.jamdesk.app/_api/search |
| Method | POST |
| Auth header | Authorization: Bearer jd_live_c83003a54ae0a83123454c3f7ec82f0a |
| Query field | query |
| Result path | results[*].content |
Use Intercom's built-in test tool to send a sample query. Verify Fin returns relevant passages from your docs.
Turn on the data connector in your Fin configuration. Fin will now cite your documentation when answering customer questions.
Fin respects the score field — higher-scoring results appear first in its answers. Passages with a score below 0.7 are typically not used.
Zendesk (MCP Server)
Zendesk's AI features support MCP servers as knowledge sources. Use Jamdesk's built-in MCP server to connect your docs to Zendesk's AI agents — no custom code required.
Your MCP server is available at https://your-project.jamdesk.app/_jd/mcp. No API key is required for the MCP server — it uses your project's public docs.
In Zendesk Admin Center, go to AI Agents → Knowledge Sources → Add MCP Server.
Paste your MCP server URL: https://your-project.jamdesk.app/_jd/mcp
Zendesk will list the available tools (searchDocs, getPage). Confirm both tools are detected, then save.
The MCP server exposes the same search index as the Docs Search API. Use the Docs Search API (with a jd_live_ key) when you need authenticated access, per-key rate limiting, or revocation control.
Custom Chatbots
Add documentation search to any chatbot or web app with a standard fetch call. CORS is enabled, so browser-based clients can call the API directly without a backend proxy.
async function searchDocs(query) {
const response = await fetch(
"https://your-project.jamdesk.app/_api/search",
{
method: "POST",
headers: {
"Authorization": "Bearer jd_live_c83003a54ae0a83123454c3f7ec82f0a",
"Content-Type": "application/json",
},
body: JSON.stringify({ query, limit: 5 }),
}
);
if (!response.ok) {
const { error } = await response.json();
throw new Error(error);
}
const data = await response.json();
return data.results;
}
// Example usage
const results = await searchDocs("How do I configure a custom domain?");
results.forEach((result) => {
console.log(`[${result.score.toFixed(2)}] ${result.title}`);
console.log(result.content);
console.log(result.url);
console.log("---");
});
Building an AI Agent Tool
Pass search results as context to a language model to generate grounded answers:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
async function answerFromDocs(userQuestion) {
// 1. Search your docs
const results = await searchDocs(userQuestion);
const context = results
.map((r) => `[${r.title}](${r.url})\n${r.content}`)
.join("\n\n---\n\n");
// 2. Pass context to Claude
const message = await client.messages.create({
model: "claude-sonnet-4-5-20241022",
max_tokens: 1024,
messages: [
{
role: "user",
content: `Answer the following question using only the provided documentation excerpts.
If the answer isn't in the docs, say so.
Documentation:
${context}
Question: ${userQuestion}`,
},
],
});
return message.content[0].text;
}
Slack Bots
Build a /docs Slack slash command that searches your documentation and posts results to any channel.
import { App } from "@slack/bolt";
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
});
app.command("/docs", async ({ command, ack, respond }) => {
await ack();
const query = command.text.trim();
if (!query) {
await respond("Usage: `/docs <your question>`");
return;
}
try {
const response = await fetch(
"https://your-project.jamdesk.app/_api/search",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.JAMDESK_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ query, limit: 3 }),
}
);
const data = await response.json();
if (data.results.length === 0) {
await respond(`No results found for: _${query}_`);
return;
}
const blocks = [
{
type: "section",
text: {
type: "mrkdwn",
text: `*Results for:* _${query}_`,
},
},
{ type: "divider" },
...data.results.flatMap((result) => [
{
type: "section",
text: {
type: "mrkdwn",
text: `*<${result.url}|${result.title}>*\n${result.content}`,
},
},
{ type: "divider" },
]),
];
await respond({ blocks });
} catch (err) {
await respond(`Error searching docs: ${err.message}`);
}
});
(async () => {
await app.start(process.env.PORT || 3000);
console.log("Slack bot is running");
})();
Set JAMDESK_API_KEY in your Slack app's environment variables — never hardcode the key.
hostAtDocs (Cloudflare Worker)
If you're using hostAtDocs to serve your docs at a subpath (e.g. yoursite.com/docs), the /_api route needs to be proxied through your Cloudflare Worker.
Add /_api to the PROXY_PATHS array in your worker:
const PROXY_PATHS = [
"/docs",
"/_jd",
"/_api", // Add this line
];
This ensures search requests to yoursite.com/_api/search are forwarded to your Jamdesk docs site.
The /_api route requires authentication via your jd_live_ API key regardless of how the request is routed. Proxying through Cloudflare does not bypass authentication.
