# API Overview

The Flomailr REST API lets your own code manage contacts, lists, campaigns, automations and forms, record events, and send transactional email. Every route lives under one base URL:

```text
https://flomailr.com/api/v1
```

## Authentication

Every request needs an API key in a bearer header:

```bash
curl https://flomailr.com/api/v1/contacts \
  -H "Authorization: Bearer flo_sk_live_..."
```

A key belongs to one workspace, and every route only sees that workspace's data. A contact, list, campaign, automation or form from another workspace answers `404`, the same as one that does not exist. Create and revoke keys under `Settings > API keys` (see [API Keys](/docs/api/api-keys)).

A request with a missing, empty, unknown or revoked key gets `401` with code `UNAUTHORIZED`.

## Response format

A single object comes back wrapped in `data`:

```json
{ "data": { "id": "clx...", "name": "Newsletter" } }
```

A list comes back with a `pagination` block:

```json
{
  "data": [{ "id": "clx...", "name": "Newsletter" }],
  "pagination": { "total": 42, "limit": 20, "hasMore": true, "nextCursor": "clx..." }
}
```

An error comes back as:

```json
{ "error": { "code": "VALIDATION_ERROR", "message": "name is required." } }
```

Successful `DELETE` requests return `204` with no body, except `DELETE /keys/:id`, which returns the revoked key's id and `revokedAt`.

## Pagination

List routes take two query parameters:

| Parameter | Meaning                                                                                |
| --------- | -------------------------------------------------------------------------------------- |
| `limit`   | Items per page. Default 20, maximum 100. A value that is not a number uses the default |
| `after`   | A cursor. Pass the previous response's `nextCursor` to get the next page               |

`nextCursor` is `null` when there are no more pages. Lists are returned newest first. `total` is the count of all items matching your filters, not just the current page.

```bash
curl "https://flomailr.com/api/v1/contacts?limit=100&after=clx123" \
  -H "Authorization: Bearer $FLOMAILR_KEY"
```

## Error codes

| HTTP | Code                     | When                                                                                               |
| ---- | ------------------------ | -------------------------------------------------------------------------------------------------- |
| 401  | `UNAUTHORIZED`           | Missing, invalid or revoked API key                                                                |
| 402  | `QUOTA_EXCEEDED`         | A send would go past your monthly sending limit                                                    |
| 403  | `FORBIDDEN`              | Sending is suspended or turned off for the workspace                                               |
| 404  | `NOT_FOUND`              | The resource does not exist in your workspace                                                      |
| 409  | `CONFLICT`               | A duplicate email on contact update, or an Idempotency-Key problem on `/send`                      |
| 422  | `VALIDATION_ERROR`       | A field is missing or invalid. Most routes use 422. `/events` and `/send` use 400 for invalid JSON |
| 422  | `CAMPAIGN_ALREADY_SENT`  | You tried to edit, schedule or send a campaign that has already been sent                          |
| 422  | `AUTOMATION_WRONG_STATE` | The automation status change is not allowed from its current status                                |
| 500  | `INTERNAL_ERROR`         | An unexpected failure. `POST /send` returns 502 when every recipient fails to send                 |

## Resources

- [API Keys](/docs/api/api-keys): create, list and revoke keys
- [Contacts](/docs/api/contacts): create, update and look up subscribers
- [Lists](/docs/api/lists): lists and list membership
- [Campaigns](/docs/api/campaigns): create, schedule and send campaigns
- [Automations](/docs/api/automations): list, edit, publish and pause flows
- [Forms](/docs/api/forms): signup forms and their embed URL
- [Events](/docs/api/events): record events from your app so automations can react
- [Transactional Send](/docs/api/send): send one message to 1 to 5 people

## MCP and AI agents

The same workspace is also reachable through the hosted MCP connector. See [Connect Your AI](/docs/ai/connect).
