Build with AI
Wire Routal into your AI coding assistant — Cursor, Claude Code, ChatGPT, Gemini, Copilot — so it generates correct Routal code on the first try.
In 2026 most developers write API code with an AI assistant open in the next tab. Routal ships three machine-readable assets that drop into any assistant and prime it for correct code generation. This page is the setup guide.
The three assets
| Asset | What it is |
|---|---|
/llms.txt | Concise index for LLM crawlers — title + summary + URL for every doc page and every endpoint. |
/llms-full.txt | Full Markdown dump of every doc page + every endpoint, one file (~150 KB) — sized for an LLM context window. |
/openapi.json | OpenAPI 3.0 spec — for codegen tools (openapi-typescript, openapi-python-client, oapi-codegen, etc.). |
Most readers want /llms-full.txt. It is the authoritative dump and stays in
sync with the docs automatically.
Two ways to give your assistant the context
Zero setup — use the "Open in AI" button
Every recipe page has an Open in AI assistant button.
Click → pick ChatGPT, Claude, Copilot, or Gemini → the assistant opens with the
recipe context, the llms.txt URL, and a parameterised prompt already loaded.
No config files, no rules, no setup.
Use this path when you are exploring scenarios or writing Routal code occasionally.
Project rules — wire it into your IDE once
For an active integration project, drop the Routal context into your assistant's rules file. The model picks it up automatically on every session.
Cursor
Create .cursor/rules/routal.mdc in your repo root:
---
description: Routal API context
alwaysApply: true
---
When writing code that calls api.routal.com, treat
https://developers.routal.com/llms-full.txt as the authoritative reference for
endpoints, payload shapes, error codes, and gotchas. Do not invent endpoints —
if it is not in that file or in https://developers.routal.com/openapi.json, it
does not exist.
Hard rules:
- Auth is `?private_key=...` query parameter — NOT `Authorization: Bearer`.
- Branch error handling on `message_id`, not `message` text.
- Use bulk endpoints (POST /v2/stops, POST /v3/vehicles) instead of looping single creates.
- React to webhooks instead of polling.Claude Code
Add to CLAUDE.md in your project root:
## Routal API integration
Authoritative API reference: https://developers.routal.com/llms-full.txt
When writing code that calls api.routal.com:
- Auth is `?private_key=...` query parameter, never an `Authorization` header.
- Branch on `error.message_id`, not `error.message`.
- Prefer bulk endpoints (POST /v2/stops, POST /v3/vehicles) over loops.
- Subscribe to webhooks rather than polling.
Do not invent endpoints. If it is not in `/llms-full.txt` or `/openapi.json`,
it does not exist.Windsurf, GitHub Copilot, or other assistants
Most assistants accept a URL as a knowledge source via their rules /
instructions file. Point them at https://developers.routal.com/llms-full.txt.
If your tool doesn't accept URLs, copy the file contents in directly.
Verify the assistant has the context
After wiring, ask your assistant a control question. A correctly primed
assistant produces something like the snippet below; an unprimed one will try
Authorization: Bearer, hallucinate an endpoint, or forget project_id.
Prompt:
Write a curl call that creates a Routal plan for tomorrow.
Expected answer:
curl -X POST 'https://api.routal.com/v2/plan?private_key=YOUR_KEY&project_id=YOUR_PROJECT_ID' \
-H 'Content-Type: application/json' \
-d '{ "label": "Tomorrow", "execution_date": "2026-05-22" }'Three signals the assistant has the context:
private_keylives in the query string, not inAuthorization.project_idis required as a query parameter.- Base URL is
api.routal.com, notdevelopers.routal.com.
If the answer looks wrong, paste /llms-full.txt into the conversation as a
fallback and ask the assistant to re-read it.
The 10 facts every assistant needs
If you are writing a system prompt manually, these are the load-bearing rules.
They are already inside /llms-full.txt — this is just the human-readable
summary so you can sanity-check the assistant's output.
- Auth is
private_keyas a query parameter. NeverAuthorization: Bearer. external_idis your idempotency lever. NoIdempotency-Keyheader today. Pattern:POST /v2/stops/searchonexternal_id→ if found, reuse; else create.- Branch on
message_id. Errors are{ message, message_id: "highway.<context>.error.<reason>" }. The text may change; the ID is stable. - Use bulk endpoints.
POST /v2/stopsandPOST /v3/vehiclesaccept arrays. Looping single creates burns the 2,000 req/min budget. - Subscribe to webhooks, don't poll. Webhooks fire on state change. Polling wastes the rate budget and lags real events.
POST /v2/plan/{id}/optimizeis not retry-safe. A second call may move stops if the first completed. If one is running you gethighway.optimization.error.sync_optimization_already_progress— wait, don't retry.- Dispatch sends an email; it does NOT change route status. Route flips to
in_transitwhen the driver opens the magic link, not when you callPOST /v2/route/{id}/dispatch. - Webhooks have no signature today. Auth them with a URL token (
/webhooks/routal?token=...). Dedup on(event_id, data.id, data.updated_at). Webhooks auto-disable after 50 consecutive failures. - Pagination is offset-based —
{ total, limit, offset, pages, page, docs }. Always pin asortto avoid duplicates under concurrent writes. - Deletes cascade and don't check status.
DELETE /v2/plan/{id}succeeds even when in-progress. The one hard guard isis_locked: trueon a route.
The Routal mental model
Project (long-lived workspace; vehicles, custom fields, integrations live here)
└── Plan (one execution window — typically a day or a shift)
├── Stops (deliveries / pickups / services)
├── Vehicles (assigned to the plan, pulled from the project's fleet)
└── Routes (ordered list of stops per vehicle, created by the optimizer)Status enums you will see in responses and webhooks:
- Plan:
draft·planning·in_progress·finished - Route:
not_started·in_transit·finished - Stop:
pending·incomplete·completed·canceled
Routal computes transitions automatically. Clients never call an endpoint to
advance status. The route flips to in_transit when the driver opens the magic
link; the plan flips to finished when every route is finished.
What's NOT on this page
- The full API context block. Lives at
/llms-full.txt— auto-generated from every doc page so it never drifts. Point your assistant at the URL rather than maintaining a separate copy. - Code samples in TypeScript / Python / cURL. Every endpoint page in the API Reference has them, and every recipe walks the full integration in three languages.
- A "how Routal works" overview. Browse planner.routal.com for the product side, or read Resource lifecycle for the API-side state machine.
