Docs Search API
Search your Jamdesk docs programmatically. Power chatbots, Slack bots, custom search, and AI agents with up-to-date answers.
The Docs Search API gives you programmatic access to your documentation content via semantic search. One endpoint (POST /_api/search) takes a natural language query and returns the most relevant passages from your docs, ranked by relevance.
Use Cases
Quick Start
Go to Project Settings → API Keys in the Jamdesk dashboard. Click Generate Key, give it a name, and copy the key. It starts with jd_live_ followed by 32 hex characters (40 chars total). It is only shown once.
Send a POST request to /_api/search on your docs subdomain:
curl -X POST https://your-project.jamdesk.app/_api/search \
-H "Authorization: Bearer jd_live_c83003a54ae0a83123454c3f7ec82f0a" \
-H "Content-Type: application/json" \
-d '{"query": "How do I set up a custom domain?", "limit": 5, "language": "en"}'The response returns an array of matching passages with relevance scores and page metadata:
{
"query": "How do I set up a custom domain?",
"language": "en",
"results": [
{
"title": "Custom Domains",
"section": "Step 4: Deploy",
"slug": "deploy/custom-domains",
"content": "To add a custom domain, go to Project Settings and enter your domain. You'll need to add a CNAME record pointing to your Jamdesk subdomain.",
"url": "https://your-project.jamdesk.app/deploy/custom-domains",
"score": 0.94
}
],
"total": 1,
"durationMs": 85
}Authentication
All requests require a Bearer token in the Authorization header.
Authorization: Bearer jd_live_c83003a54ae0a83123454c3f7ec82f0a
The Search API works on sites with password or JWT authentication. It checks your API key, not a visitor's login. You don't need to add /_api/search to auth.jwt.public. Results can include pages behind the login. Call the API from your server and never put the key in browser code. Results follow the same rules as site search: group-restricted pages are never returned. Hidden pages and pages with search: false are left out unless you've made them searchable.
The same key also opens the MCP server, .md page URLs and llms.txt and llms-full.txt on these sites.
Generating API Keys
In the Jamdesk dashboard, navigate to your project and click Settings.
Select the API Keys tab.
Click Generate Key, enter a descriptive name (e.g. "Intercom chatbot"), and click Create.
Copy the key immediately. It starts with jd_live_ followed by 32 hex characters. It is shown only once. Store it in your secrets manager or environment variables.
Key Management
API keys are scoped to one project. A key for acme.jamdesk.app cannot query a different project's documentation.
| Rule | Detail |
|---|---|
| Format | jd_live_<32 hex chars> (40 chars total, never expires) |
| Scope | One key per project (cannot access other projects) |
| Rotation | Revoke and regenerate anytime from Project Settings |
| Storage | Store in environment variables or a secrets manager; never commit to source control |
Revoking Keys
Go to Project Settings → API Keys, find the key by name, and click Revoke. Revoked keys stop working immediately. Generate a new key to replace it.
Rate Limits
Requests are rate-limited per API key.
| Plan | Limit |
|---|---|
| Pro | 60 requests / minute |
| Enterprise | Custom; contact support |
On a login-protected site, MCP, .md and llms.txt requests made with the same key share a separate limit of 120 requests per minute. They don't count against the Search API limit, and Search API requests don't count against theirs.
When you exceed the limit, the API returns 429 Too Many Requests with a Retry-After: 60 header and {"error": "Rate limit exceeded"} in the body.
Contact us about Enterprise options for higher rate limits on a production integration.
Query Limits
Each request accepts a limit parameter controlling how many results to return. The maximum is 20, the default is 5, and the minimum is 1. There is no pagination. All matching results come back in one response. For more context, try a more specific query instead of a higher limit.
A query with no matches returns HTTP 200 with an empty results array:
{"query": "quantum entanglement", "results": [], "total": 0, "durationMs": 48}
Filtering by language
On a multi-language site, the API filters results to one language per request. Pass language in the request body with a BCP-47 code (e.g. en, es, fr, pt-BR, zh-Hans).
curl -X POST https://your-project.jamdesk.app/_api/search \
-H "Authorization: Bearer jd_live_c83003a54ae0a83123454c3f7ec82f0a" \
-H "Content-Type: application/json" \
-d '{"query": "¿Cómo configuro un dominio personalizado?", "language": "es"}'
| Rule | Detail |
|---|---|
| Default | en (English). Omit the field, or pass null, to use the default. |
| Format | BCP-47 (^[a-zA-Z]{2,3}([-_][a-zA-Z]{2,4})?$). Examples: en, es, fr, pt-BR, zh-Hans. |
| Validation | Malformed values return 400 with {"error": "Invalid language code"}. |
| 3-segment tags | Not currently supported. Codes like zh-Hant-HK and sr-Latn-RS return 400. Contact support if you need them. |
| Multi-language projects | The filter is strict: only chunks tagged with the requested language are returned. A request for de against a project that only has English and French returns an empty result set, not a 400. |
| Single-language projects | The filter is ignored. You always get the full result set. Sending language does not cause an error. |
| Echoed in response | Every successful response includes a language field with the value the server resolved (request value, or en default). |
A project is multi-language when its docs.json has a navigation.languages array with two or more entries. Check the Settings → Languages tab in the dashboard, or docs.json, to see whether your site is multi-language.
The default en applies even on projects that don't have an English version. A French-and-Spanish project called without a language field filters for en and returns an empty result set. Always pass an explicit language from sites without English.
Error Handling
All error responses include a machine-readable error field you can branch on programmatically.
| Status | error value | Meaning | Action |
|---|---|---|---|
| 400 | Missing or empty "query" field | Request body is missing or has no query | Add a non-empty query string |
| 400 | Invalid language code | The language field is not a string or doesn't match the BCP-47 pattern (null is fine; empty/whitespace strings and 3-segment tags are not) | Use a valid 1- or 2-segment code like en, es, fr, or pt-BR |
| 401 | invalid_key_format | Authorization header is missing or the key doesn't match jd_live_<32 hex> | Check the header format; it must be Bearer jd_live_... |
| 401 | invalid_key | Key is not recognized or has been revoked | Generate a new key in the dashboard |
| 403 | wrong_project | Key is valid but was generated for a different project | Use a key that matches the project slug in the URL |
| 429 | Rate limit exceeded | Exceeded 60 requests per minute | Wait the number of seconds in the Retry-After header |
| 502 | Search temporarily unavailable | Vector search backend is down | Retry after a short backoff |
| 503 | lookup_failed or redis_unavailable | Key verification backend is unreachable | Retry after a short backoff |
401 and 403 are permanent failures. Retrying with the same key won't help. 429, 502, and 503 are transient. Retry them with exponential backoff.
CORS
CORS is enabled on all endpoints. Browser-based clients (single-page apps, browser extensions, static sites) can call /_api/search directly without a backend proxy. All origins are allowed.
SDKs
There are no official language SDKs at this time. Use the REST API directly via fetch, requests, curl, or any HTTP client. The Postman collection below provides ready-to-fork examples.
Versioning
The API is currently at v1.0.0. Breaking changes (field renames, removed endpoints, changed auth) will be announced via the Jamdesk blog and a deprecation notice in the X-Deprecation response header at least 90 days before removal.
OpenAPI Specification
The full OpenAPI 3.1 spec is available as YAML. Import it into your codegen tool, API client, or contract-testing pipeline.
Postman Collection
We publish an official Postman workspace with the full OpenAPI spec and a ready-to-fork collection. Test requests in the Postman UI without writing code.
Update two collection variables in the forked collection. No request works until you do:
baseUrl: set to your own Jamdesk docs site. This is usuallyhttps://your-project.jamdesk.app(replaceyour-projectwith your project slug). On a custom domain, use your own host. For docs under a sub-path, include the full path (e.g.https://example.com/docs).apiKey: replace the placeholder with a real key generated in Dashboard → Project Settings → API Keys.
