The documentation site serves every page to software over public, read-only addresses. None of them needs a sign-in.
An agent can read the page index, one page as markdown, all pages in one file, the pages that match a query, or the OpenAPI documents. It can also call a Model Context Protocol server, MCP for short, that serves the documentation pages through tools.
This page covers reading the documentation. To let an agent operate DALP, see CLI for AI agents, whose dalp -- server runs dalp commands against the Platform API, or Hosted MCP server, which runs inside a DALP deployment.
The addresses on this page are relative to the documentation host, https://. A DALP deployment also serves its own copy of the pages under /docs on its hostname. To call your own deployment, keep the path and replace the host. That copy builds these absolute links from the host in its PUBLIC_URL environment variable:
- the
llms.txtandllms-full.txtindexes - the
Source:line of each markdown page - the canonical
Linkheader of each markdown response - the canonical and Open Graph tags of each page
- the URLs that MCP
searchandlist_pagesreturn
The DALP Helm chart sets PUBLIC_URL from the hostname that serves the documentation, unless the operator overrides it. Documentation host explains how the chart picks it.
Call these addresses from a script or a server-side client. The MCP and search endpoints answer 403 when a request has Sec- or an Origin header for another origin. They send no cross-origin resource sharing headers, so a page on another origin cannot call them. The 403 body is the plain text Forbidden, not JSON-RPC.
Choose an endpoint
A crawl can read the index, then fetch each page with .md. The links in the table open the public host.
The OpenAPI documents in the table are the contract built with this documentation. To generate a client for a running deployment, fetch that deployment's own /api/v2/spec.json, as the API reference overview describes.
Page markdown
A page answers as markdown in two ways. Append .md to the page path, or send Accept: text/ to the page URL. The root page /docs is the exception: its .md address is /docs/index.md. Both forms return the same markdown with the same headers.
DOCS=https://docs.settlemint.com
curl -sSD - "$DOCS/docs/api-reference/webhooks/consuming.md"
curl -sSD - -H 'Accept: text/markdown' "$DOCS/docs/api-reference/webhooks/consuming"Both calls return 200 and a markdown body that starts with a # Title line and a Source: line with the canonical URL. The headers that matter to a client are:
Content-Type: text/markdown; charset=utf-8
Link: <https://docs.settlemint.com/docs/api-reference/webhooks/consuming>; rel="canonical"
Vary: Accept
Cache-Control: public, max-age=300, s-maxage=900, stale-while-revalidate=3600For the Accept form, the types text/markdown, text/x-markdown and text/plain count as markdown. A q-value is the weight from 0 to 1 that a client gives a type, and 1 is the default. Markdown wins when the highest q-value among the markdown types is greater than 0 and at least the highest q-value among text/html, text/* and */*. A request with no Accept header, or with */* alone, returns the HTML page.
An HTML response for a page that has a markdown form includes Link: </, which points an agent to that form. An unknown page has no markdown form, so its HTML response has no such header.
The two forms differ only when a page has no markdown form:
The 404 body for an unknown page reads:
# Page not found
No markdown page exists at /docs/no/such/page. The index at /docs/llms.txt lists every page.The 406 body is {"error":"Only HTML requests are supported here"}. To get the HTML answer instead, add the HTML type to the header: Accept: text/. A moved page then answers 301 to its new HTML path, and an unknown path answers 404 HTML.
MCP endpoint
POST /docs/ is a Model Context Protocol server over streamable HTTP, which lets the server answer a request with an event stream. Requests and replies use JSON-RPC, a JSON message format for remote procedure calls. The public site serves the endpoint at https://. Each request stands alone: there is no session.
This section describes requests in the protocol revisions up to 2025-11-25, which have no _meta envelope. The MCP-Protocol-Version header is optional for them. A request that names an older revision the server does not support gets 400, and the error message lists the supported older revisions. Revision 2026-07-28 uses a different request format, with its own headers and a _meta envelope in params. This page does not describe it. A request in that format that breaks its rules gets 400 with a JSON-RPC error code.
A request needs three things:
Content-. Another type gets 415.Type: application/ json - An
Acceptheader that lists bothapplication/jsonandtext/event-stream.*/*does not count, and a request without both gets 406. - The
POSTmethod.GETandDELETEanswer 405.
tools/call works without an earlier initialize call. This request uses the DOCS variable from Page markdown and asks for a page that does not exist:
curl -sS -X POST "$DOCS/docs/api/mcp" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"get_page","arguments":{"url":"/docs/no/such/page"}}}'The reply is an event stream with one message, and the response sends Cache-:
event: message
data: {"result":{"content":[{"type":"text","text":"page not found: /docs/no/such/page"}],"isError":true},"jsonrpc":"2.0","id":1}The server offers three tools. Send tools/list for the exact input schemas.
get_page reports a problem in the result, not in the HTTP status, which stays 200 with isError set to true. A missing page gives the text page not found: <input>. The same result comes back for a URL on another host, a moved page and an API explorer page, because get_page reads only documentation pages at their present path, and an API explorer page is not one of them. Read an API explorer page with .md.
A missing or mistyped argument gives Input validation error: ... with the same isError.
A request for a tool that does not exist returns a JSON-RPC error object with code -32602 in place of result. A body that is not valid JSON gets 400.
Search endpoint
GET /docs/ matches page titles, descriptions, headings and body text, and returns a JSON array.
A page whose title holds every searched word comes before a page that only mentions them. Title words match whole and ignore case and accents, without stemming. The last word may be half typed, from two letters. Only the first 201 records the engine finds are reordered.
Each matched page gives one record for the page and up to eight records for text fragments on it. Every record has id, type, content and url. A page record has type set to page, the page title in content and a breadcrumbs list. A fragment record has type set to heading or text and a url that usually ends in an anchor. A heading record has the heading text in content. A text record has the text fragment in content. A text record that comes from a table row holds the header row and that row as a markdown table in content, and has a table key that names the table. This request uses the DOCS variable from Page markdown, holds the search to one section and raises the cap:
curl -sSD - "$DOCS/docs/api/search?query=retries&tag=api-reference&limit=100"The reply sends X- and an X-Docs-Search-Truncated header, and its body is an array of records. This is one page record from such a reply:
{
"id": "/docs/api-reference/webhooks/consuming",
"type": "page",
"content": "Consuming events",
"breadcrumbs": ["Documentation", "API reference", "Webhooks"],
"url": "/docs/api-reference/webhooks/consuming"
}Every 200 response reports the cap it applied in X-Docs-Search-Limit. X- means more records exist: raise limit up to 200, then narrow the query or add tag. false does not prove the array holds every match, because a page contributes at most eight fragments. The endpoint has no offset, page or cursor parameter. Send only query, tag and limit: a search with a query and mode=vector answers 500, because the index holds no embeddings.
Three groups of error pages are not in the search index: the error index at /, and the two error references at / and / with every code-range page under them. Find them through llms.txt, or open the error index and follow the link for the code's range.
The MCP search tool takes query and locale, and ignores locale. It has no tag and no limit: it returns at most 60 records, with a page whose title holds every searched word ahead of a page that only mentions them. Nothing in the reply says whether more records exist, so use the HTTP endpoint when you need to know whether the result was cut, or need more than 60 records.
MCP search records have full page URLs on the PUBLIC_URL host, such as https://, while list_pages returns .md URLs. get_page accepts both.
Limits and freshness
The MCP endpoint allows 60 requests per minute for each client, and search allows 300. Both budgets count HTTP requests, not tool calls. The initialize and tools/list calls each use one request, and so does a GET that gets 405. A client over its budget gets status 429, the plain text body Too many requests and a Retry-After header in seconds. The 429 body is not JSON-RPC. The Retry-After value depends on the cause:
The server counts a client by the address that a configured trusted proxy forwards. A deployment with no trusted proxy configured counts every caller as one client, and all callers share one budget. A request whose forwarded address is missing or invalid also counts against that shared budget. The default install sets DOCS_CHAT_TRUSTED_PROXY, the setting that names the trusted proxy for these budgets and for the docs chat, to none, as Ask AI provider key in the install values reference describes. A 429 can then come from other callers' traffic: wait for Retry-After before you send again. On a deployment behind Cloudflare that sets DOCS_CHAT_TRUSTED_PROXY to envoy, the server counts each caller by the address Cloudflare adds to X-Forwarded-For when the operator has configured Envoy Gateway as Count readers separately behind Cloudflare describes. Otherwise callers that arrive through the same Cloudflare address share a budget. A deployment that has no Redis store keeps a separate budget on each server instance.
Three kinds of 200 response send Cache-: markdown pages in either form, the llms.txt and llms-full.txt files at both the /docs/... path and the root path, and the two OpenAPI JSON files. Error responses, redirects and search replies send none, and MCP event-stream replies send Cache-. A browser or agent can reuse a response for 5 minutes. A shared cache holds it fresh for 15 minutes and can serve it for up to 60 more minutes while it fetches a new copy, so an answer can be 75 minutes behind the server.
The server builds llms-full.txt on the first request after it starts and reuses that text until it restarts, so the first request takes longer than the ones after it.
When a request fails
Every endpoint on this page only reads, so any request is safe to send again. Retry a 429 after its delay, and retry a 5xx or a timeout with your own backoff. Fix the request and resend for 400, 403, 405, 406 and 415. Do not retry a 404 or an isError result with the same input. A search with a query and mode=vector answers 500 every time, so remove mode instead of retrying.
Related
- CLI for AI agents: run the
dalpclient from an agent. - API explorer: browse the v2 OpenAPI contract.
- API reference overview: authenticate and integrate the Platform API.