# Build with AI

Markdown twins, llms.txt, the spec URL, and the two MCP servers.

These docs are published for two readers: you, and whatever agent is helping
you integrate. Everything the human pages say also exists in a machine-shaped
form — a markdown twin of every page, an index and a single-file corpus for
LLMs, the OpenAPI description the reference is generated from, and two MCP
servers: one that answers from the real pages, and one that reads — and,
scope permitting, operates — a store's live data through the API itself.
This page is where each one lives and how to point your tools at it.

None of it is required to use the API. It exists so an agent reads what these
docs actually say instead of guessing from APIs that merely resemble ours.

## Markdown for every page

Append `.md` to any docs URL and you get that page as raw markdown — no nav
chrome, no highlighting markup, just the content:

| Human page                                         | Markdown twin                                         |
| -------------------------------------------------- | ----------------------------------------------------- |
| `https://www.shopdeskbd.com/developers/pagination` | `https://www.shopdeskbd.com/developers/pagination.md` |

The overview's twin is `/developers.md`, and the generated reference follows
the same rule — `/developers/reference/orders.md` is the orders reference as
markdown.

Two files cover the corpus as a whole:

- [`/llms.txt`](https://www.shopdeskbd.com/llms.txt) — the index, per the
  llms.txt convention: every page as an absolute `.md` link with a one-line
  summary. Give this to tools that crawl and follow links.
- [`/llms-full.txt`](https://www.shopdeskbd.com/llms-full.txt) — every page
  concatenated in sidebar reading order. Give this to tools that read: it
  fits comfortably in a modern context window, so pasting it into a chat
  hands the model the entire documentation at once.

Every page header also carries a **Copy page** button that copies the page's
markdown twin, and a menu that opens the page in Claude or ChatGPT with the
twin's URL already in the prompt.

## The OpenAPI description

The API is described by one published OpenAPI document:

```text
https://www.shopdeskbd.com/openapi/public-v1.json
```

It is the same artifact the [reference](https://www.shopdeskbd.com/developers/reference.md) pages are
generated from, so the two cannot disagree — anything the spec declares, the
reference shows, and nothing in the reference was written by hand.

One URL unlocks the usual tooling: generate a typed client, import the
collection into Postman or Insomnia, or hand it to a ChatGPT GPT Action,
which takes an OpenAPI URL directly.

## Add the docs to your tools

**Cursor** — Settings → Indexing & Docs → Add Doc, then paste
`https://www.shopdeskbd.com/llms.txt`. Cursor indexes the linked pages and
cites them in chat.

**Claude Code** — connect the MCP server with the one-liner in the next
section. Without MCP, telling it to fetch
`https://www.shopdeskbd.com/llms.txt` and follow the links it needs works
nearly as well.

**ChatGPT** — a GPT Action takes the OpenAPI URL above directly; for
questions rather than calls, paste `/llms-full.txt` into the conversation.

**Everything else** — any agent that can fetch a URL can read the `.md`
twins, and any tool that accepts a document can take `/llms-full.txt`.

## The docs MCP server

The docs run a Model Context Protocol server at:

```text
https://www.shopdeskbd.com/developers/mcp
```

Transport is Streamable HTTP, and there is no authentication — it serves the
same public pages you are reading and nothing else.

| Tool             | Answers                                                        |
| ---------------- | -------------------------------------------------------------- |
| `search_docs`    | Where in the docs a term or topic is covered.                  |
| `get_page`       | One page in full, as markdown, by slug.                        |
| `list_endpoints` | Every operation, optionally narrowed to one resource.          |
| `get_endpoint`   | One operation in detail — parameters, scope, examples.         |
| `list_mcp_tools` | Every store MCP tool, optionally only those one scope unlocks. |
| `get_mcp_tool`   | One store MCP tool in detail — scopes, arguments, output.      |

Every tool is read-only and says so (`readOnlyHint`), and an argument it does
not know is refused by name.

For Claude Code, one command:

```bash
claude mcp add --transport http shopdesk-docs https://www.shopdeskbd.com/developers/mcp
```

For other MCP clients, the generic configuration block:

```json
{
  "mcpServers": {
    "shopdesk-docs": {
      "type": "http",
      "url": "https://www.shopdeskbd.com/developers/mcp"
    }
  }
}
```

> **Note — Docs only — it cannot touch a store**
>
> This server takes no API key and makes no API calls. It answers questions
> about the documentation; creating an order still means calling the API,
> with your key, under the same
> [idempotency contract](https://www.shopdeskbd.com/developers/idempotency.md) as any other client.

## The store MCP server

The API itself also speaks MCP. A second server exposes a store's live data
as curated tools, at:

```text
https://api.shopdeskbd.com/ext/mcp/v1
```

Transport is Streamable HTTP, and it authenticates exactly like the REST API:
the same `Authorization: Bearer` header, the same
[keys](https://www.shopdeskbd.com/developers/authentication.md), the same tenant boundary. The key the
connection carries decides which company — and, for a store key, which
store — every tool can see, and each tool requires the same
[scope](https://www.shopdeskbd.com/developers/authentication.md#scopes) as its REST counterpart (a tool
that combines several reads requires all of their scopes). **Each key lists
only its own tools**: `tools/list` shows the tools whose scopes the key holds,
so an agent never sees a tool it cannot call.

Every tool is documented on [MCP tools](https://www.shopdeskbd.com/developers/mcp-tools.md) — scopes,
arguments, metering and output — generated from the tool manifest the server
publishes at `https://www.shopdeskbd.com/openapi/mcp-tools-v1.json`.

Eight tools answer the questions a merchant asks most, in one call each:

| Tool                            | Answers or does                                                                                                                                |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `get_store_profile`             | The store — currency, timezone, contact — and what this key can reach.                                                                         |
| `get_sales_summary`             | Sales for a window (`period` such as `last_7_days`, or dates), with money received and COD to collect; optionally against the previous period. |
| `list_low_stock`                | What needs restocking, with product names.                                                                                                     |
| `find_orders`                   | Orders by order number, customer name or phone number in any form.                                                                             |
| `list_orders_needing_attention` | The call queue: unconfirmed orders, or call-backs now due.                                                                                     |
| `get_customer_summary`          | A customer by id or phone, with their order history and latest orders.                                                                         |
| `update_order_details`          | Sets an order's note and call-back time.                                                                                                       |
| `record_call_outcome`           | Records a confirmation call — confirmed, cancelled, call back or no answer.                                                                    |

These answer **concisely** by default — the fields needed to act, names
beside ids — and take `response_format: "detailed"` for the full objects.
The [COD confirmation guide](https://www.shopdeskbd.com/developers/guide-cod-confirmation.md#with-the-store-mcp-server)
walks through them.

Twelve more tools read, one per REST read:

| Tool                               | Answers                                                                                   |
| ---------------------------------- | ----------------------------------------------------------------------------------------- |
| `list_products` / `get_product`    | Products with their variants nested — the sellable units — and their ready videos.        |
| `list_categories` / `list_brands`  | Catalog metadata, searchable by name; ids feed the product filters.                       |
| `list_orders` / `get_order`        | Orders, compact by default, expandable with `customer` and `items`.                       |
| `list_order_payments`              | Every payment row recorded against one order.                                             |
| `list_customers` / `get_customer`  | Customer records, searchable; the detail includes addresses and, on request, order stats. |
| `get_inventory_levels`             | Stock per variant per location, with a `low_stock` filter.                                |
| `list_locations` / `list_channels` | Warehouses and sales channels.                                                            |

And ten write — one per core [write endpoint](https://www.shopdeskbd.com/developers/idempotency.md),
running the same engine the merchant's own staff use, so a tool call cannot
do anything the dashboard could not.

| Tool                                                    | Does                                                                                                                    |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `create_order`                                          | Places an order: stock reserved, totals computed server-side, coupons priced by the real engine.                        |
| `update_order_status` / `cancel_order`                  | Status moves under the same strict transition map as the desk.                                                          |
| `record_order_payment`                                  | Records a payment already received, capped at the order's net due. It moves no money.                                   |
| `create_customer` / `update_customer`                   | Customer records, with per-store phone/email uniqueness.                                                                |
| `adjust_inventory`                                      | A signed, audited stock change — `reason` required, on-hand can never go negative.                                      |
| `create_product` / `update_product` / `archive_product` | Catalog writes, variants included. `create_product` also takes up to 10 photo links and each variant's options by name. |

Five more build a catalog — attributes, categories and brands, photos by
link, and one variant at a time. The
[catalog guide](https://www.shopdeskbd.com/developers/guide-build-a-catalog.md#with-the-store-mcp-server)
walks through them.

| Tool                               | Does                                                                                                             |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `create_attribute`                 | Makes sure an attribute exists with the values listed; if it does, adds only the missing values. Safe to repeat. |
| `create_category` / `create_brand` | A category (parent by name, slug or id) or a brand, with images by link.                                         |
| `add_product_images_from_urls`     | Adds up to 10 photos to a product from links, all or nothing.                                                    |
| `update_variant`                   | Changes one variant's price, sale price, SKU, barcode, weight or photo, by id, SKU or barcode.                   |

One more puts a video on a product. The
[video guide](https://www.shopdeskbd.com/developers/guide-upload-a-product-video.md#with-the-store-mcp-server)
walks through it.

| Tool                   | Does                                                                                                                                                                                                                         |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `attach_product_video` | Imports an MP4 from a link and places it on a product, or places a video the key already uploaded — for every variant, or for one option value such as Colour: Red. With no video, it returns the upload steps for a script. |

The tools that take links — `create_product`, `create_category`,
`create_brand`, `add_product_images_from_urls` and `attach_product_video` —
declare `openWorldHint: true`, because they download from outside the store
(through the same checks as the REST API: see
[Photos by link](https://www.shopdeskbd.com/developers/guide-photos-by-link.md)); every other tool declares
`false`. Photo reordering, edits and deletes, multipart uploads, catalog
updates, and the video upload session, covers and deletes stay on REST.

The write tools are opt-in, and the opt-in is the key: each tool requires
the same write scope as its REST twin, so a key minted with read scopes
simply cannot write — it does not even list them. Writes carry the
[idempotency contract](https://www.shopdeskbd.com/developers/idempotency.md) as an `idempotency_key`
argument — required on `create_order`, `record_order_payment`,
`adjust_inventory`, and `attach_product_video` when it imports a
`video_url`; honoured everywhere else. The rules are the header's,
verbatim: one unique value per logical operation, the same value on every
retry of it, replays answer with the original result.

List tools page exactly like the REST API — pass `meta.next_cursor` back as
`starting_after` until it comes back null. Every tool declares an
`outputSchema` and answers with `structuredContent`, plus the same value as
minified JSON text. The REST mirrors return what their REST twins return,
because each calls the same service its twin calls — a write answers with the
object re-read through the public serializer (or, for `archive_product`, the
same small `{ id, archived }` receipt).

One difference is deliberate: **text a shopper wrote is returned as data.**
Order and follow-up notes, delivery addresses, customer names and emails, and
checkout answers come back in labelled fields, at most 500 characters, with links,
markup and hidden characters removed — so a note that reads like an
instruction reaches the model as a quoted value, never as something to follow.
The REST API returns those fields unchanged.

Tool calls count against the key's [rate limits](https://www.shopdeskbd.com/developers/rate-limits.md#the-store-mcp-server):
reads against the read limit (the two summary tools as 5 reads each), writes
against the write limit. A call to a tool the key does not list counts as a
write.

A call that fails comes back as a tool result with `isError: true`, and its
text is the REST error object — `{ "error": { code, message, fields? } }`,
with the same stable codes. When a name the call used matches nothing or
several rows (an option name on `create_product`, a parent category), the
error object also carries `candidates`: the rows it could have meant, names
beside ids. A tool the key does not list is refused as an
unknown tool. The request id is not in that text: it is in the
result's `_meta.request_id`, the same value as the exchange's `X-Request-Id`
header, so it reaches your logs without being handed to the model. Failed tool
calls count as errors on the dashboard's API usage page.

For Claude Code, one command (the key travels as a header):

```bash
claude mcp add --transport http shopdesk-store https://api.shopdeskbd.com/ext/mcp/v1 --header "Authorization: Bearer shopdesk_sk_your_key_here"
```

For other MCP clients:

```json
{
  "mcpServers": {
    "shopdesk-store": {
      "type": "http",
      "url": "https://api.shopdeskbd.com/ext/mcp/v1",
      "headers": {
        "Authorization": "Bearer shopdesk_sk_your_key_here"
      }
    }
  }
}
```

> **Warning — The key in that config is a real credential**
>
> Anything the agent can do, that config file can do. Create a dedicated key
> holding only the scopes you intend the agent to use — read scopes for an
> agent that answers questions, write scopes only when you mean for it to
> operate the store — keep the config out of version control, and
> [revoke](https://www.shopdeskbd.com/developers/authentication.md#rotation) the key if the machine or
> the config leaks.

## Drop this in your repo

If a coding agent works on your integration, put a short description of this
API where your agent reads instructions — an `AGENTS.md`, a `CLAUDE.md`, a
system prompt. The block below is deliberately compact: enough to make
correct calls, with links to where everything else lives.

```markdown
## Shopdesk Commerce API

- REST API over a Shop Desk store's live data: products, orders, customers,
  inventory, locations and sales channels. JSON in, JSON out.
- Base URL: `https://api.shopdeskbd.com/ext/v1`
- Auth: `Authorization: Bearer <key>`. Keys start with `shopdesk_sk_` and are
  created in the dashboard under Settings → Developer. Server-side only.
- Errors: every failure is `{ error: { code, message, request_id } }`.
  Branch on `code` — it is stable. `message` is human copy and may be
  reworded at any time. Validation failures add a `fields` map.
- Writes: send an `Idempotency-Key` header (any unique value up to 255
  characters; a UUID is ideal) and reuse the SAME key when retrying the
  same operation. Required on `POST /orders`, `POST /orders/{id}/payments`
  and `POST /inventory/adjustments`; honoured on every other write.
- Pagination: cursor-based. Pass `limit` (max 100) and `starting_after` =
  the previous page's `meta.next_cursor`; stop when `next_cursor` is null.
- Machine-readable docs:
  - OpenAPI: https://www.shopdeskbd.com/openapi/public-v1.json
  - Docs index: https://www.shopdeskbd.com/llms.txt
    (whole corpus in one file: https://www.shopdeskbd.com/llms-full.txt)
  - Docs MCP, Streamable HTTP, no auth: https://www.shopdeskbd.com/developers/mcp
  - Store MCP (live store data through curated read + write tools, gated by
    the key's scopes, same Bearer key): https://api.shopdeskbd.com/ext/mcp/v1
    (tool manifest: https://www.shopdeskbd.com/openapi/mcp-tools-v1.json)
```

The facts in that block are the same ones documented on
[Getting started](https://www.shopdeskbd.com/developers/getting-started.md),
[Errors](https://www.shopdeskbd.com/developers/errors.md),
[Writes & idempotency](https://www.shopdeskbd.com/developers/idempotency.md) and
[Pagination](https://www.shopdeskbd.com/developers/pagination.md) — when in doubt, those pages are the
authority, and an agent with the MCP server attached can check them itself.
