Developers
usedocs developer portal
The Docs API and MCP server keep your help center in step with your code from CI and AI tools; the Answer API and docs MCP server get answers with sources without scraping HTML.
Quickstart
- Sign in at the dashboard with Google, GitHub, or a magic link. Every workspace starts with a 7 day free trial of Growth, no credit card.
- Import your docs (a docs site URL, Zendesk Guide, Intercom, GitBook, Notion, or OpenAPI), then open Settings → API and MCP.
- Copy
botIdand the publicbotKey. They are the keys for the widget, the Answer API, and the docs MCP server. - Call
POST /chat, or connect an agent to usedocs.app/mcp.
API keys
There are two kinds of credentials. The public Answer API and the docs MCP server use the embed credentials:
- botId: the bot's UUID, in the path and the JSON body.
- botKey: the public key from Settings → API and MCP, sent in the JSON body as
botKey. - Browser calls also need an
Originheader on an allowed origin. Server to server calls authenticate with botKey; send Origin when the bot has allowed origins configured.
The Docs API and the workspace MCP server use a workspace API key from Settings → API and MCP, sent as Authorization: Bearer ud_live_…. A key is shown once and stored as a hash. A content:read key can read; a content:write key can also edit, publish, apply drafts, and send code changes. A key covers one bot or all of them and can be revoked at any time. Keys don't work on the dashboard's own routes, settings, or billing. People connecting Claude, Cursor, or ChatGPT sign in with OAuth instead (Integrations → AI clients).
Docs API
Read and change your help center from your own tools and CI, at https://usedocs.app/v1: articles, drafts waiting for review (with diffs), revisions, collections, the changelog, unanswered questions, doc health, tasks, and webhooks. The full reference is usedocs.app/v1/openapi.json.
- Auth.
Authorization: Bearer ud_live_…. A key that covers several bots names one with?bot_id=or theUsedocs-Botheader;GET /v1/botslists them. - Pages. Lists take
page_size(1 to 100, default 20) andstart_cursor, and return{results, has_more, next_cursor}. - Content. Articles come as
contentMarkdown, orcontentHtmlwith?format=html. - Errors.
{error, code}with an HTTP status:insufficient_scope,plan_inactive(paused workspace; reads still work),rate_limited,bot_required,not_found. - Drafts. Everything waiting for review has a typed id:
edit_…(a proposed edit to an article),article_…(a new article usedocs wrote),gap_…(a draft from customer questions).GET /v1/drafts/{id}returns the text and a unified diff;POST /v1/drafts/{id}/applyapproves it.
curl 'https://usedocs.app/v1/articles?status=published&page_size=50' \
-H "Authorization: Bearer $USEDOCS_API_KEY"
Update the docs from CI
Send a code change as a task. usedocs reads the diff against your docs and proposes edits to the articles it affects, new articles it needs, and a changelog entry, the same as for a merged pull request on the GitHub app, from any code host. Tasks only propose: nothing goes live until someone applies it. Send an Idempotency-Key so a retried job doesn't run twice, then poll GET /v1/tasks/{id} or subscribe to task.completed.
# .github/workflows/docs.yml
on:
pull_request:
types: [closed]
jobs:
docs:
if: github.event.pull_request.merged
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Send the change to usedocs
env:
USEDOCS_API_KEY: ${{ secrets.USEDOCS_API_KEY }}
TITLE: ${{ github.event.pull_request.title }}
URL: ${{ github.event.pull_request.html_url }}
run: |
git diff ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.merge_commit_sha }} |
jq -Rs --arg t "$TITLE" --arg u "$URL" '{change: {kind: "pr", title: $t, url: $u, diff: .}}' |
curl -sS -X POST https://usedocs.app/v1/tasks \
-H "Authorization: Bearer $USEDOCS_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: ${{ github.sha }}" --data-binary @-
# .gitlab-ci.yml
docs:
rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' }]
script:
- git diff "$CI_COMMIT_BEFORE_SHA...$CI_COMMIT_SHA" |
jq -Rs --arg t "$CI_COMMIT_TITLE" '{change: {kind: "pr", title: $t, diff: .}}' |
curl -sS -X POST https://usedocs.app/v1/tasks -H "Authorization: Bearer $USEDOCS_API_KEY"
-H "Content-Type: application/json" -H "Idempotency-Key: $CI_COMMIT_SHA" --data-binary @-
OpenAPI specification
Two machine readable specs: the Docs API at usedocs.app/v1/openapi.json, and the Answer API and widget endpoints at usedocs.app/openapi.json. Every operation has a unique operationId, typed parameters, and JSON error schemas, so LLM function calling can import the files directly. There is no GraphQL surface.
Answer API
The same retrieval as the widget, over HTTP. Full reference: Answer API.
curl -sS -X POST 'https://usedocs.app/chat' \
-H 'content-type: application/json' \
-d '{
"botId": "YOUR_BOT_ID",
"botKey": "YOUR_PUBLIC_BOT_KEY",
"question": "How do I get started?",
"visitor": "ticket-system"
}'
Errors are JSON objects with error, code, message, and hint, never HTML error pages on API paths.
MCP servers
The usedocs MCP server for docs speaks Streamable HTTP JSON-RPC at usedocs.app/mcp, with discovery at /.well-known/mcp.json. Tools: ask_docs, search_docs, get_bot_config. Pass botId and botKey in each tool's arguments.
{
"mcpServers": {
"usedocs": { "url": "https://usedocs.app/mcp" }
}
}
The workspace MCP server at https://usedocs.app/mcp/admin manages your help center from Claude, Claude Code, ChatGPT, Cursor, Codex, or any MCP client, with the same operations as the Docs API: search_articles, get_article, create_article, update_article, publish_article, list_drafts, get_draft (with a diff), propose_edit, apply_draft, dismiss_draft, list_changelog, create_changelog_entry, create_task (send the change you're working on), get_task, list_gaps, doc_health, and check_articles. Prompts: document_my_change and review_docs.
Each teammate connects their own client with OAuth sign-in and acts as themselves; setup steps for each client are in Integrations → AI clients. In Claude Code:
claude mcp add --transport http usedocs https://usedocs.app/mcp/admin
An agent that can't sign in (a CI job) uses a workspace API key; content:read keys only see the read tools.
{
"mcpServers": {
"usedocs": {
"url": "https://usedocs.app/mcp/admin",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}
Rate limits
Public chat allows 30 requests per 60 seconds per visitor (policy widget-chat). The Docs API and workspace MCP server allow 120 calls a minute per key or connection, and 30 tasks an hour. The free SEO tools have their own hourly limits. Responses include RFC 9237 RateLimit and RateLimit-Policy headers, and HTTP 429 also sends Retry-After. Honor those headers instead of guessing a backoff.
Webhooks
Add endpoints in Settings → API and MCP, or with POST /v1/webhooks. Events: article.published, article.updated, article.unpublished, article.deleted, edit.proposed, draft.created, changelog_entry.published, task.completed, conversation.escalated, lead.created. Each delivery is a JSON POST with usedocs-event, usedocs-delivery, and usedocs-signature: t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of <t>.<raw body> with the endpoint's signing secret.
Deliveries are logged with status and timing. A delivery that fails (no answer within 10 seconds, or a non 2xx status) is retried after 5 and 30 minutes, then 2, 8, and 24 hours, with the same usedocs-delivery id and a usedocs-attempt count, so dedupe on the delivery id. Handoff and lead alerts for chat tools have their own webhook integration.
Sandbox
Try the widget without an account in the live demo. For API calls, start a trial, import a public docs URL, and use that bot's keys. Every page here also has a Markdown copy: curl -H 'Accept: text/markdown' https://usedocs.app/developers returns this page as Markdown with Vary: Accept.