# Get started with the REST API

> Base URL, token authentication, agent_id, idempotency keys, cursors, and the error shape. Rules shared by every API page.

## Base URL

```text
https://api.atmark.ai
```

Only the public identity lookup uses `https://id.atmark.ai`. See [Identity lookup](https://docs.atmark.ai/en/api/identity).

## Authentication

Send the agent token in a header with every request. Never put it in the query string or body.

```http
Authorization: Bearer atk_agent_...
```

- A missing, wrong, revoked, or expired token returns `401 unauthorized`.
- A token without the needed scope, or a request for another agent's data, returns `403 forbidden`.
- Organization API keys (`atk_org_…`) don't work here. See [Organization API keys](https://docs.atmark.ai/en/team/org-api-keys).

## agent_id

Many requests take an `agent_id` (32 lowercase hex characters) in the body or query. It must match the token's agent. Copy the agent ID from the agent's overview or from **Identity › Identifiers** in the console.

## Idempotency keys

Requests that send mail or create schedules need an `Idempotency-Key` header (1–255 characters). Without it you get `400 idempotency_key_required`.

- Keys are scoped per agent and have no set expiry. Sending, replying, and forwarding share one key space; creating schedules has its own.
- Repeat the same request with the same key and no second email goes out. Instead you get the message's **current state** with `replayed: true`. See [Replayed requests](https://docs.atmark.ai/en/api/messages#replay).
- Use the same key for a different request and you get `409 idempotency_key_reused`.
- After a timeout, a network error, a `500`, or a `503`, wait a little and retry with **the same key**. If the mail already went out, it won't go out twice.
- A key that got `403 policy_denied` stays denied. After fixing the cause, or waiting `retry_after_seconds`, send with a **new key**.

## Lists and cursors

Lists take `limit` and `cursor` and return `next_cursor`. A `null` `next_cursor` means you've reached the end. Keep the same filters when asking for the next page.

## Error shape

```json
{ "error": "invalid_request", "detail": "…" }
```

Only branch on `error`. `detail` is for people and its wording can change. A first `403 policy_denied` response carries `message_id` and `decision` instead of `detail`. See [Messages](https://docs.atmark.ai/en/api/messages#results). See [Error codes](https://docs.atmark.ai/en/api/errors).

## Times

All times are ISO 8601 UTC strings, for example `2026-09-27T09:00:00.000Z`.

## Endpoints

| Method | Path | Docs |
|---|---|---|
| `POST` | `/v1/messages` | [Messages](https://docs.atmark.ai/en/api/messages) |
| `POST` | `/v1/threads/{threadId}/reply` | [Messages](https://docs.atmark.ai/en/api/messages#reply) |
| `POST` | `/v1/messages/{messageId}/forward` | [Messages](https://docs.atmark.ai/en/api/messages#forward) |
| `GET` | `/v1/messages/inbound` | [Received mail](https://docs.atmark.ai/en/api/inbound) |
| `GET` | `/v1/messages/inbound/{messageId}` | [Received mail](https://docs.atmark.ai/en/api/inbound#get) |
| `GET` | `/v1/messages/inbound/{messageId}/attachments/{index}` | [Received mail](https://docs.atmark.ai/en/api/inbound#attachment) |
| `GET` | `/v1/threads/{threadId}` | [Threads](https://docs.atmark.ai/en/api/threads) |
| `GET` | `/v1/approvals/{approvalId}` | [Approvals](https://docs.atmark.ai/en/api/approvals) |
| `GET` | `/v1/agents/{agentId}/policy` | [Policy](https://docs.atmark.ai/en/api/policy) |
| `POST` · `GET` | `/v1/messages/scheduled` | [Scheduled email](https://docs.atmark.ai/en/api/scheduled) |
| `GET` | `/v1/messages/scheduled/{scheduleId}` | [Scheduled email](https://docs.atmark.ai/en/api/scheduled#get) |
| `POST` | `/v1/messages/scheduled/{scheduleId}/cancel` | [Scheduled email](https://docs.atmark.ai/en/api/scheduled#cancel) |
| `GET` | `/v1/messages/verification-code` | [Verification codes](https://docs.atmark.ai/en/api/verification-code) |
| `GET` | `/v1/audit` | [Audit records](https://docs.atmark.ai/en/api/audit) |
| `POST` · `GET` · `DELETE` | `/v1/agents/{agentId}/webhook-endpoints…` | [Webhooks](https://docs.atmark.ai/en/api/webhooks) |
| `GET` · `POST` | `/v1/agents/{agentId}/webhook-deliveries…` | [Webhooks](https://docs.atmark.ai/en/api/webhooks#deliveries) |
| `GET` | `https://id.atmark.ai/v1/identity/{address}` | [Identity lookup](https://docs.atmark.ai/en/api/identity) |

---

Source: https://docs.atmark.ai/en/api/overview · Last updated 2026-09-27
