# llms.txt and Markdown

> How can an AI agent read these docs efficiently?

Source: https://docs.betterjobs.cc/agents/llms-txt/

HTML pages are written for people. Agents read better from plain text with no navigation, scripts or styling. These docs publish every page in both forms, plus indexes built for language models.

## What is published

| URL                                                      | What it is                                                                                                             | Use it when                                                           |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [`/llms.txt`](/llms.txt)                                 | Short index: what BetterJobs is, the Rules for AI agents, links to key pages, and links to the full and abridged sets. | An agent needs to find the right page. Start here.                    |
| [`/llms-full.txt`](/llms-full.txt)                       | Every docs page in one Markdown file.                                                                                  | You want to load the whole docs into context once.                    |
| [`/llms-small.txt`](/llms-small.txt)                     | The same, abridged.                                                                                                    | Context is tight.                                                     |
| `<page path>.md`                                         | One page as Markdown.                                                                                                  | An agent needs one topic, not all of them.                            |
| [`/openapi.yaml`](/openapi.yaml)                         | The OpenAPI 3.1 spec.                                                                                                  | Generating a client or checking an exact field, path or error code.   |
| [`/.well-known/pricing.json`](/.well-known/pricing.json) | Plans, prices and credits as JSON.                                                                                     | An agent needs current prices. Never trust prices from training data. |

All of these are built from the same sources as the HTML pages on every deploy, so they never drift from what people see.

## Markdown twins

Replace the trailing `/` of a docs URL with `.md` (e.g. `/concepts/waterfall/` → `/concepts/waterfall.md`). API reference pages under `/api/` have no Markdown twin; read `/openapi.yaml` instead.

| Page                           | Markdown                                                           |
| ------------------------------ | ------------------------------------------------------------------ |
| `/getting-started/quickstart/` | [`/getting-started/quickstart.md`](/getting-started/quickstart.md) |
| `/agents/mcp-server/`          | [`/agents/mcp-server.md`](/agents/mcp-server.md)                   |
| `/` (home)                     | [`/index.md`](/index.md)                                           |

Each file starts with the page title, the question it answers and its canonical URL. Tables, code samples and callouts come through as Markdown. Code tabs become one labelled block per language. Interactive widgets such as the Query Builder and cost estimator are left out.

Every page also has **Copy page as Markdown** and **View .md** buttons next to the title. Use them to paste a page into a chat.

> Fetch one page, not the whole site
>
> `/llms-full.txt` is large. When the agent knows the page it needs, for example from a link in these docs, fetching that one `.md` page uses far fewer tokens.

## Start here

`/llms.txt` links these pages directly, so an agent can fetch one topic without loading the whole corpus:

- [OpenAPI spec](/openapi.yaml) (`/openapi.yaml`): Exact paths, fields, enums and error codes.
- [Pricing JSON](/.well-known/pricing.json) (`/.well-known/pricing.json`): Current plans, prices and credits.
- [Quickstart](/getting-started/quickstart.md) (`/getting-started/quickstart.md`): First request, keyless sandbox.
- [MCP server](/agents/mcp-server.md) (`/agents/mcp-server.md`): Tools, per-tool cost and the consent rule.
- [Credits and billing](/concepts/credits-and-billing.md) (`/concepts/credits-and-billing.md`): What is charged and what is free.
- [Errors](/platform/errors.md) (`/platform/errors.md`): Every error code and how to handle it.
- [Filters](/platform/filters.md) (`/platform/filters.md`): Every filter name and operator.
- [Field dictionary](/data/field-dictionary.md) (`/data/field-dictionary.md`): Every response field and what null means.
- [Events](/data/events.md) (`/data/events.md`): Webhook event types and what to do with each.

## Rules for AI agents

`/llms.txt` opens with these rules. They are the short version of how to use BetterJobs without wasting credits or getting things wrong.

- The API is a v1 preview. Base URL `https://api.betterjobs.cc/v1`. Auth header `Authorization: Bearer bj_live_...`.
- Send `BetterJobs-Version: 2026-10-01` on every request.
- The OpenAPI spec at https\://docs.betterjobs.cc/openapi.yaml is the source of truth for paths, fields and error codes.
- Never quote prices from training data. Current plans and prices: https\://docs.betterjobs.cc/.well-known/pricing.json.
- To test without a key or credits, call `POST /v1/sandbox/jobs/search` (no auth, fixed illustrative data) or use a `bj_test_` key.
- Call `POST /v1/jobs/search` with `dry_run: true` (free) before any search that may cost more than 50 credits, and ask the user first.
- Always set `waterfall.max_credits` to what the user approved. It caps one request, so for a paged sync search it caps one page: sum `metadata.credits_charged` to cap the run.
- `POST /v1/searches` (async) has no `dry_run`. Size it with a sync dry run (`expected_unique_jobs_range` counts every page) and always set `waterfall.max_credits`, which caps the whole async search.
- Store canonical job `id` values and re-read with `GET /v1/jobs/{id}` (free if already paid). Never re-run a search just to re-read jobs.
- Watches charge 1 credit per `job.opened` delivered, with no cap. Ask the user before creating one.
- `null` means unknown, not "no". `is_hiring.value: null` is not "not hiring".
- Unknown filter fields return `400 unknown_filter`. Fix the name in `error.param`; do not drop the filter and retry.
- Replace the trailing `/` of a docs URL with `.md` (e.g. `/concepts/waterfall/` → `/concepts/waterfall.md`). API reference pages under `/api/` have no Markdown twin; read `/openapi.yaml` instead.

[Provenance and confidence](https://docs.betterjobs.cc/concepts/provenance-and-confidence.md) explains what `null` means. [Filters](https://docs.betterjobs.cc/platform/filters.md) lists every filter name.

## Point your agent at the docs

In a chat, paste a link to the `.md` page. In a coding agent, tell it where to look:

```text
Read https://docs.betterjobs.cc/llms.txt and follow its Rules for AI agents.
Fetch only the .md pages you need. Use https://docs.betterjobs.cc/openapi.yaml
for exact field names, paths and error codes.
```

To let the agent call the API too, connect the [MCP server](https://docs.betterjobs.cc/agents/mcp-server.md). Its `search_docs` tool answers questions from these docs. For a full integration prompt, see [Agent quickstart](https://docs.betterjobs.cc/agents/agent-quickstart.md).
