> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lanesurf.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> You are reading the Lanesurf Agent API docs. Start with /for-ai-agents.md for the rules an agent must follow.
> The API is at https://agent.lanesurf.com and the MCP server at https://agent.lanesurf.com/mcp. Lanesurf doesn't send webhooks: poll.
> Limits: /rate-limits.md. Keys: /api-keys.md. Safe retries: /idempotency.md. Every route on one page: /api-reference.md.
> Always confirm with the person before accepting a carrier offer or bidding on a load. Never reveal an API key, and never show broker contact details to a carrier.
> The full contract is at /openapi.yaml.
> Sign up with POST /v1/signup (carrier or broker, a work email, an MC and/or DOT number), then POST /v1/signup/{signup_id}/verify. Follow next_step on every signup answer.

# Connect over MCP

> Use Lanesurf as tools in Claude, Cursor, Grok and other MCP clients.

Lanesurf is a remote MCP server (streamable HTTP) at:

```text theme={null}
https://agent.lanesurf.com/mcp
```

Add it to your AI app by URL. You don't need an API key first: the app opens a Lanesurf sign-in page, where
an existing Lanesurf customer signs in and a new brokerage or carrier signs up. Every tool is one REST route,
with the same limits and error codes.

## Add Lanesurf to your app

> [tab] Claude
>
> In Claude (web, desktop or Cowork), on Free, Pro, Max and Ultra plans:
>
> 1. Open **Customize → Connectors**, choose **+ Add**, then **Add custom connector**.
> 2. Name it `Lanesurf`, paste `https://agent.lanesurf.com/mcp` as the URL and choose **Continue**.
>    Keep the sign-in settings Claude detects (OAuth, no client ID or API key needed) and choose **Add**.
> 3. Choose **Connect**. Claude opens the Lanesurf sign-in page; sign in or sign up, then allow access.
> 4. In a chat, open **+ → Connectors**, turn on Lanesurf, and ask, for example, "Post a load on Lanesurf".
>
> On Team and Enterprise plans, an owner adds Lanesurf once under **Organization settings → Connectors →
> Add → Custom → Web** with the same URL. Each member then connects it and signs in themselves.

> [tab] ChatGPT
>
> Custom MCP servers in ChatGPT need developer mode, which a workspace admin turns on (Business,
> Enterprise and Edu workspaces, on ChatGPT web).
>
> 1. Open **Plugins**, choose **+**, then **Add custom MCP server**. (Some workspaces show this as
>    **Settings → Apps → Create**.)
> 2. Name it `Lanesurf`, paste `https://agent.lanesurf.com/mcp` as the URL, and choose **OAuth** for
>    authentication.
> 3. ChatGPT opens the Lanesurf sign-in page; sign in or sign up, then allow access.
> 4. In a chat, add Lanesurf from the tools menu.

> [tab] Claude Code
>
> ```bash theme={null}
> claude mcp add --transport http lanesurf https://agent.lanesurf.com/mcp
> ```
>
> Then run `/mcp` in Claude Code, pick **lanesurf** and choose **Authenticate**. Your browser opens the
> Lanesurf sign-in page; after you allow access, the tools are ready. With an API key instead:
>
> ```bash theme={null}
> claude mcp add --transport http lanesurf https://agent.lanesurf.com/mcp \
>   --header "Authorization: Bearer $LANESURF_API_KEY"
> ```

> [tab] Cursor and others
>
> Add the URL to `mcp.json`. Cursor opens the Lanesurf sign-in page when you first use it:
>
> ```json theme={null}
> {
>   "mcpServers": {
>     "lanesurf": { "url": "https://agent.lanesurf.com/mcp" }
>   }
> }
> ```
>
> To use an API key instead, add `"headers": { "Authorization": "Bearer ls_live_..." }`. Other clients that
> support remote MCP servers (the OpenAI Responses API, Grok and others) take the same URL, with OAuth
> sign-in or the key header.

See [Sign in from an AI app](https://docs.lanesurf.com/authentication.md#sign-in-from-an-ai-app) for what the sign-in page asks for.

> [!NOTE]
>
> `/mcp` needs credentials: an API key or an OAuth token. A request without either gets `401` with a
> `WWW-Authenticate` header pointing at `/.well-known/oauth-protected-resource/mcp`, which is how an app
> finds the sign-in page.

## Keys

* **No key:** `/mcp` answers `401`. An app that supports MCP sign-in opens the Lanesurf sign-in page,
  where an existing customer signs in and a new carrier or brokerage signs up. An agent without MCP
  sign-in signs up over plain HTTP (`POST /v1/signup`, no key needed), then connects with the key.
  See [Carrier sign up](https://docs.lanesurf.com/carriers/sign-up.md) and [Sign up your brokerage](https://docs.lanesurf.com/brokers/get-a-key.md).
* **Broker key:** `whoami`, the load tools and the setup tools.
* **Carrier key:** `whoami` and the carrier tools. Carriers under review (`needs_review`) get
  `verification_required` on search, load details, matches, outreach and bids.
* A wrong key gets HTTP `401`; another role's tool gets `wrong_role`.

## Tools

| Tool | Route | Key |
| - | - | - |
| `whoami` | `GET /v1/me` | any |
| `list_loads` | `GET /v1/loads` (`limit`, `cursor`, `status`, `needs_decision`) | broker |
| `post_load` | `POST /v1/loads` (`idempotency_key`, required, is the `Idempotency-Key`) | broker |
| `get_load` | `GET /v1/loads/{id}` | broker |
| `load_outreach` | `GET /v1/loads/{id}/outreach` | broker |
| `accept_offer`, `decline_offer` | `POST /v1/loads/{id}/offers/{session_id}/accept`, `/decline` (`accept_offer` needs `rate`) | broker |
| `mark_covered` | `POST /v1/loads/{id}/covered` | broker |
| `edit_load` | `PATCH /v1/loads/{id}` (`load_id` plus the fields that change) | broker |
| `pause_load`, `resume_load`, `reopen_load` | `POST /v1/loads/{id}/pause`, `/resume`, `/reopen` | broker |
| `delete_load` | `DELETE /v1/loads/{id}` | broker |
| `get_broker_setup`, `update_broker_setup` | `GET`, `PATCH /v1/broker/setup` | broker |
| `start_signup`, `verify_signup` | `POST /v1/signup`, `/{signup_id}/verify` | none over HTTP; over MCP the connection itself needs a key or sign-in (see Keys) |
| `post_truck`, `list_trucks`, `get_truck`, `update_truck`, `remove_truck` | `/v1/carrier/trucks` (`post_truck` takes an optional `idempotency_key`) | carrier |
| `truck_matches` | `GET /v1/carrier/trucks/{truck_id}/matches` | verified carrier |
| `save_lane`, `list_lanes`, `remove_lane` | `/v1/carrier/lanes` | carrier |
| `search_loads`, `get_carrier_load` | `GET /v1/carrier/loads/search`, `/{load_id}` | verified carrier |
| `bid_on_load` | `POST /v1/carrier/loads/{load_id}/bids` | verified carrier |
| `list_bids` | `GET /v1/carrier/bids` | carrier |
| `my_outreach` | `GET /v1/carrier/outreach` | verified carrier |

Tool inputs follow the REST fields in the [API reference](https://docs.lanesurf.com/api-reference.md), with the same limits. Numbers such
as `limit` or `rate` may also be sent as strings (`"1250"`, `"$1,250"`); one that isn't a number is refused
with `invalid_request`, never ignored. Where a tool differs from its route:

* Path and header values are arguments: `load_id`, `truck_id`, `session_id`, `idempotency_key`.
* `list_trucks` takes `include_inactive` (`true` also lists removed and expired trucks) instead of `?active=false`.
* `remove_truck` and `remove_lane` return `{"removed": true, "truck_id": "…"}` (or `lane_id`) instead of an empty `204`.

## Errors

A failed tool returns an error result whose text is the same JSON body as the REST API
(`{"error": "...", "code": "...", "next_step": "...", "request_id": "..."}`), so branch on `code` exactly as in [Errors](https://docs.lanesurf.com/errors.md). Some failures come
back as HTTP errors on the request instead, before any tool runs:

| HTTP | `code` | When |
| - | - | - |
| `401` | `missing_api_key` | No key or OAuth token (the `WWW-Authenticate` header points at sign-in) |
| `401` | `invalid_api_key` | A wrong, malformed or revoked key |
| `400` | `invalid_request` | A JSON-RPC batch (send one message per request), or a body that can't be read |
| `413` | `invalid_request` | The body is over 1 MB |
| `429` | `rate_limited` | Over a limit. Wait `Retry-After` seconds |
| `503` | `unavailable` | Lanesurf couldn't check the key right now. Wait `Retry-After` (30) seconds; the key may be fine |

A successful result carries its request id in `_meta["lanesurf/request_id"]`. Quote it to
[support@lanesurf.com](mailto:support@lanesurf.com) when something keeps failing. See [Request IDs](https://docs.lanesurf.com/errors.md#request-ids).

## Rules the server gives the agent

* **Confirm with the person** before `accept_offer`, `decline_offer`, `mark_covered`, `edit_load`, `pause_load`,
  `resume_load`, `reopen_load`, `delete_load` or `bid_on_load`. `resume_load` and `reopen_load` restart carrier outreach.
* To change, pause, cancel or reopen a load, use those tools. Never post it again or mark it covered instead.
* `post_load` needs `idempotency_key`: a new UUID per load, sent unchanged on any retry of that load.
* `accept_offer` needs the `rate` the person agreed to. `offer_changed`: the carrier changed its rate
  (`current_rate`); ask the person again before accepting.
* `load_rejected`: don't send the same load again; check its stops and dates with the person.
* `existing_customer`: the brokerage already uses Lanesurf. Don't sign up; their Lanesurf admin gives them access.
* When something keeps failing, tell the person to quote the `request_id` to [support@lanesurf.com](mailto:support@lanesurf.com).
* Never reveal the API key, and never show broker contact details to a carrier. (`search_loads`,
  `get_carrier_load` and `truck_matches` hide broker identity; `my_outreach` names the brokerage that
  contacted the carrier, with no contacts.)
* `stalled` on a load means nobody has been contacted (or a new brokerage's outreach starts after Lanesurf's
  review): tell the person `status_reason` and slow down or stop polling.
* Follow `next_step` on signup, `post_load` and `get_load` answers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.