# API overview

Base URL, authentication, errors, and pagination for the REST API.

## Base URL & authentication

One base URL, one kind of credential. Every endpoint authenticates with an API key as a bearer token — create one under **Developers → API Keys**.

```
https://emailbump.com/api/v1
```

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

## Start here

Two calls answer "what is this API and what may I do with it", so nothing has to be guessed at:

```bash
curl https://emailbump.com/api/v1                    # the index — no key needed
curl https://emailbump.com/api/v1/me -H "Authorization: Bearer ebk_your_key"
```

`GET /v1/me` is the one to make before your first send. It names the project the key belongs to, whether the account's email is confirmed, which sending domains are verified, the `from` address to use, and whether the compliance footer carries your own postal address or our placeholder. Every one of those can refuse a send, and reading them beforehand beats interpreting the refusal.

```json
{
  "project": { "id": "7a10f0f2-…", "name": "Main", "object": "project" },
  "sending": {
    "ready": true,
    "email_confirmed": true,
    "verified_domains": ["mail.acme.com"],
    "default_from": "hello@mail.acme.com",
    "note": "Ready. `from` must be an address on one of the verified domains."
  },
  "footer": { "address": "12 Bridge Street, Austin TX", "is_your_own_address": true }
}
```

## No account yet

`POST /v1/signup` creates one from the command line — an email address, no password, no browser:

```bash
curl -X POST https://emailbump.com/api/v1/signup \
  -H "Content-Type: application/json" \
  -d '{ "email": "you@company.com", "name": "Dana", "accept_terms": true }'
```

It returns a **project key** for sending and an **account key** for creating further projects and keys. The account cannot send until the six-character code we email is confirmed with `POST /auth/verify-email/code`. See [Authentication](https://emailbump.com/docs/api-keys).

## Two halves, one API

Everything lives under the same base URL, and every reference page says at the top which key reaches it. The split is only about what a resource belongs to:

- **Project API** — what you send and who you send it to: contacts, events, lists, segments, templates, campaigns, flows, transactional email. A **project key** reaches these directly.
- **Account API** — the structure those projects live in: workspaces, projects, project keys, sending domains. Needs an **all-access key**, and is mostly for agents and CLIs setting an account up.

An all-access key can do both: it reaches any project resource too, by naming the project per call with an `X-Project-Id` header. A project key stays inside its own project. See [Authentication](https://emailbump.com/docs/api-keys).

One exception, because it was the wrong side of the line: a project key manages **its own project's sending domains** at `/v1/domains` — list, add, check. Setting up sending is the first thing a project needs to do, and it shouldn't require the wider credential.

## Pagination

Contacts, campaigns, flows, and flow enrollments are paginated: they accept `?limit=` (max 100, default 25) and `?offset=`, and return `{ "data": [...], "total", "limit", "offset" }`. Lists, segments, and templates are small by nature and return the full set as `{ "data": [...] }`. Every call you make appears under **Developers → API Keys → Recent API calls**.

## Plan limits and usage

`GET /v1/limits` reports the plan, contact usage, and how much of this month's sending allowance is left, so an integration can back off or prompt an upgrade before it hits the wall.

```bash
curl https://emailbump.com/api/v1/limits \
  -H "Authorization: Bearer ebk_your_key"
```

```json
{
  "plan": "growth",
  "plan_name": "Growth",
  "contacts": { "count": 8412, "limit": 25000 },
  "sending": {
    "this_month": 31204,
    "included_per_month": 250000,
    "remaining": 218796,
    "over_limit": false
  },
  "features": { "automations": true, "custom_domains": true }
}
```

A `0` contact limit and a `null` `included_per_month` both mean unmetered.

## Tracing a sent message

Every message Email Bump sends — API, SMTP, campaign, or flow — carries two headers that say where it came from, so a forwarded email or a bounce report can be tied back to a project without a database lookup:

```
X-EmailBump-Project: 7a10f0f2-3b44-4c19-9c6e-2f81a6d4e0aa
X-EmailBump-Stream: transactional
```

`X-EmailBump-Stream` is `transactional`, `marketing` (campaigns), or `automation` (flows). The project id is the same value you would pass as `X-Project-Id`.

Inside Email Bump the same ids ride along as provider message tags — project, stream, and the campaign, flow, step, or A/B variation responsible — which is what the reports join on. **Developers → Transactional** has every API and SMTP send with its provider message id, rendered content, and event timeline; **Developers → API Keys → Recent API calls** has the request that caused it.

## Unrecognised fields

On `/v1/emails`, a field we don't read is ignored but not silently — the response carries a `warnings` array naming it. `from_name` is the one that bites: it's a real field on campaigns and flows, and here the display name belongs in `from` (`"Acme <hi@acme.com>"`). A typo that changes nothing is worth hearing about at the time.

**Everywhere else an unknown field is ignored silently.** A misspelled `first_nmae` on `/v1/contacts` returns `200` with nothing said, and the field it was meant to set is simply unchanged. Check the response body reflects what you sent rather than trusting the status code.

## Errors

Errors always return a single consistent shape with the right HTTP status. Successful reads and writes return `200`; deletes return `204`.

```json
{ "error": "Enter a valid email address" }
```

- `400` — invalid or malformed request body / validation failed
- `401` — missing or invalid API key
- `402` — upgrade required for a paid feature (adds `code`, `feature`, and `upgrade_to` fields)
- `404` — resource not found (or not in your project)
- `409` — conflict (e.g. a contact with that email exists)
- `429` — shared-domain daily send limit reached

## Project resources

One page per thing you can act on, all reachable with a project key:

- [Transactional](/docs/transactional-api) — `/v1/emails`, one-off & scheduled sends, and `GET /v1/emails/{id}` for what became of one
- [Domains](/docs/domains-api) — `/v1/domains`, this project's sending domains
- [Contacts](/docs/contacts-api) — `/v1/contacts`, create, update, list, consent
- [Events](/docs/events-api) — `/v1/events`, track behaviour
- [Lists](/docs/lists-api) — `/v1/lists`, audiences & membership
- [Segments](/docs/segments-api) — `/v1/segments`, read live queries
- [Templates](/docs/templates-api) — `/v1/templates`, reusable MJML content
- [Campaigns](/docs/campaigns-api) — `/v1/campaigns`, send & schedule marketing
- [Flows](/docs/flows-api) — `/v1/flows`, automated journeys
- [Inbound](/docs/inbound-api) — `/v1/inbound`, email people send you
- [Webhooks](/docs/webhooks-api) — receive events at your own URL

## Account resources

The provisioning half, for standing an account up. Needs an all-access key:

- [Workspaces](/docs/workspaces-api) — `/v1/workspaces`, the billing container
- [Projects](/docs/projects-api) — `/v1/projects`, projects and their keys
- [Domains](/docs/domains-api) — sending domains and DNS verification
