# REST API

Every MCP tool is also a REST operation with the same input and result. Use it from scripts, backends, Zapier-style tools and agents that call HTTP APIs instead of MCP (Delegated's Custom APIs, for example).

**Base URL:** `https://api.tandemcrm.app`
**Auth:** `Authorization: Bearer crm_sk_…` (see [Authentication](/docs/authentication))

## List operations

```bash
curl https://api.tandemcrm.app/v1/ops -H "Authorization: Bearer $TANDEM_API_KEY"
```

Returns `{ "operations": [{ "name", "description", "scope", "mutating", "input_schema" }] }` for the operations your key may call. `input_schema` is JSON Schema.

## Run an operation

```bash
curl -X POST https://api.tandemcrm.app/v1/ops/upsert_company \
  -H "Authorization: Bearer $TANDEM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-acme-1" \
  -d '{"name": "Acme", "domain": "acme.com", "source": {"name": "My script"}}'
```

The body is the operation's input; the response is its result as JSON.

## Idempotency

Writes accept an `Idempotency-Key` header (over MCP, an `idempotency_key` argument). A retry with the same key returns the first result instead of writing twice. Keys are kept for 24 hours.

## Errors

Errors are JSON with an HTTP status:

```json
{ "error": { "code": "not_found", "message": "Stage 'Won' not found.", "hint": "Use one of: lead, qualified, proposal, negotiation, won, lost." } }
```

`hint` tells the caller, often a model, what to do next. See [Errors and limits](/docs/errors-and-limits).

## Other endpoints

| Endpoint | Who | What |
| --- | --- | --- |
| `GET /v1/export` | Owners and admins, signed in | The whole workspace as a ZIP of CSV and JSON. |
| `GET /v1/people/:id/export` | Owners and admins, signed in | Everything about one person, as JSON (data subject access). |
| `POST /v1/people/:id/erase` | Owners and admins, signed in | Erase a person, and by default add them to the do-not-contact list. |
| `GET/POST/DELETE /v1/api-keys` | Owners and admins, signed in | Manage API keys. |
| `POST /v1/import` | Signed-in people | Import CSV rows (the app's importer uses it). |
