# REST API

The Dewstack REST API returns your published documentation as JSON or markdown, so you can sync it into a search index, a support tool, or your own product's in-app help. Three endpoints, one [API key](/docs/api-and-agents/api-keys), no SDK required.

Base URL:

https://app.dewstack.com/api/public/v1

Every request carries the key as a bearer token:

curl https://app.dewstack.com/api/public/v1/articles \\
  -H "Authorization: Bearer dsk\_3f9a1c47e0b28d5641fa9e7c30bd48a2159cd7e0"

Missing or malformed headers return `401` with the message _"Missing or invalid API key. Pass `Authorization: Bearer dsk_...`."_; an unknown or revoked key returns `401 Invalid or revoked API key.`

## List every published page

GET /v1/articles

Returns every published page in the key's workspace, up to 500, with the URL each one is served at. This is the endpoint to poll when you want to know what exists.

{
  "data": {
    "articles": \[
      {
        "id": 41822,
        "name": "Point a custom domain at your docs",
        "slug": "custom-domain",
        "collection\_slug": "hosting",
        "url": "https://docs.acme.com/docs/hosting/custom-domain",
        "updated\_at": "2026-07-14T09:22:41.000Z"
      }
    \]
  }
}

`updated_at` is the field to diff against on a re-sync – fetch full content only for the pages whose timestamp moved.

## Fetch one page

GET /v1/articles/{collection\_slug}/{article\_slug}
GET /v1/articles/{collection\_slug}/{article\_slug}?format=markdown

Without `format`, `content` is the page's HTML. With `format=markdown`, it is markdown – which is usually what you want if the destination is a language model, a chat tool, or anything that will re-render the content itself.

curl "https://app.dewstack.com/api/public/v1/articles/hosting/custom-domain?format=markdown" \\
  -H "Authorization: Bearer $DEWSTACK\_KEY"

{
  "data": {
    "article": {
      "id": 41822,
      "name": "Point a custom domain at your docs",
      "slug": "custom-domain",
      "collection\_slug": "hosting",
      "url": "https://docs.acme.com/docs/hosting/custom-domain",
      "format": "markdown",
      "content": "## Add the CNAME record\\n\\n…",
      "updated\_at": "2026-07-14T09:22:41.000Z"
    }
  }
}

## Ask a question

POST /v1/ask

Runs a question through [SmartDocs](/docs/smartdocs/what-is-smartdocs) – the same engine behind the _Ask a question_ widget on your docs site – and returns a written answer grounded in your content.

curl -X POST https://app.dewstack.com/api/public/v1/ask \\
  -H "Authorization: Bearer $DEWSTACK\_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{"question": "How do I move a collection into another tab?"}'

{
  "data": {
    "answer": "Open Settings → Customize → Spaces (Tabs)…",
    "conversation\_id": "c8b1f2e4-…"
  }
}

Pass the returned `conversation_id` back on the next call to ask a follow-up in the same thread.

This endpoint spends message credits

`/v1/ask` draws on the same SmartDocs message quota as the widget on your docs site. When the quota is exhausted the endpoint returns `429`. The other two endpoints are free, and so is [MCP](/docs/api-and-agents/mcp).

## Errors

| Status | When |
| --- | --- |
| 400 | POST /v1/ask with no question |
| 401 | Missing, malformed, unknown or revoked key |
| 404 | No published page at that collection and page slug |
| 429 | Rate limit exceeded, or SmartDocs message quota exhausted |
| 502 | The SmartDocs service is unreachable |

## Limits

*   **60 requests per 60 seconds** per key. Space out bulk syncs.
*   **500 articles** maximum per response.
*   **Published pages only.** Drafts are never returned.
*   Reads are **one workspace per key**. To sync two workspaces, create two keys.

## Related

[Configuring SmartDocs Enable it, train it, style the widget and embed it elsewhere.](/docs/smartdocs/configuring-smartdocs) [llms.txt and llms-full.txt Whole-corpus text files at your docs root.](/docs/ai-ready-docs/llms-txt)
