# Building with AI

You can build on the Understory API with AI coding tools such as Claude Code, Cursor, ChatGPT, Lovable or v0.
This page lists the machine-readable versions of these docs and the rules to give your assistant, so the code it writes uses the API the way it is meant to be used.

## Machine-readable docs

| Resource | Where |
|  --- | --- |
| `llms.txt`: an index of every page, with the rules below | [developer.understory.io/llms.txt](https://developer.understory.io/llms.txt) |
| Any page as Markdown | Add `.md` to the page URL, for example [/docs/quickstart.md](https://developer.understory.io/docs/quickstart.md), or request the page with `Accept: text/markdown` |
| API reference as Markdown: every operation with a link to its own Markdown page | [developer.understory.io/apis.md](https://developer.understory.io/apis.md) |
| OpenAPI description | [YAML](https://developer.understory.io/_spec/apis/index.yaml) or [JSON](https://developer.understory.io/_spec/apis/index.json) |


Every page also has a **Copy** button at the top, with options to copy the page as Markdown or open it in Claude or ChatGPT.

Point your assistant at `llms.txt` first.
For a specific task, give it the Markdown pages it needs, for example the authentication guide and the operations you call.

## Rules for your assistant

AI-generated integrations often get the same few things wrong, most commonly by requesting a new access token for every API call.
Paste these rules into your assistant's project instructions, such as `AGENTS.md`, `CLAUDE.md` or Cursor rules, so they apply to all the code it writes.

AGENTS.md
```markdown AGENTS.md
**Rules for code that calls the Understory API**

Docs: https://developer.understory.io/llms.txt

- Base URL: `https://api.understory.io`. Every path starts with a major version, for example `/v1/bookings`.
- Authentication: OAuth2.0. Get an access token from `https://api.auth.understory.io/oauth2/token` with `grant_type=client_credentials`, `audience=https://api.understory.io`, the `client_id`, the `client_secret` and space-separated `scope` values. Send it as `Authorization: Bearer <token>`.
- Cache the access token and reuse it for every request until shortly before `expires_in` (about one hour) runs out. Never request a token per API call: the token endpoint and the API are rate limited.
- On `401 Unauthorized`, get a new token and retry once. `403 Forbidden` means a scope is missing; a new token will not help.
- Send a descriptive `User-Agent` and `Accept: application/json` on every request.
- Lists are paginated with `cursor` and `limit`. Pass back the exact `next` value as `cursor` until `next` is empty. Never store or build cursors.
- To keep data in sync, subscribe to webhooks and fetch the resource when notified. Do not poll list endpoints.
- On `429 Too Many Requests`, back off before retrying. Do not retry immediately.
- Errors return JSON with a machine-readable `code` and a human-readable `message`.
- Accept unknown fields and unknown values of enums documented as extensible. New ones are added without a new API version.
- Endpoints marked `Preview` cannot be called yet; `Alpha` endpoints work but can still change.
```

The same rules open [`llms.txt`](https://developer.understory.io/llms.txt), so an assistant that reads it picks them up too.

## See also

- [Quickstart](/docs/quickstart)
- [Authentication](/docs/usage/authentication)
- [OpenAPI Description](/docs/about/openapi-description)