# Developer overview

> Base URL, authentication, object IDs, errors, pagination, rate limits, SDKs, webhooks and MCP. The conventions every Emailit integration shares.

This page collects the conventions you need before you write code against Emailit: where the API lives, how requests are authenticated, how objects are identified, and how errors, pagination and rate limits work. Each section links to the detailed reference.

## Ways to integrate

| Interface | Endpoint | Use it for |
| --- | --- | --- |
| REST API | `https://api.emailit.com/v2` | Sending email and managing every resource from code. |
| SMTP relay | `smtp.emailit.com` | Apps, frameworks and CMSs that already speak SMTP. See [SMTP settings](/docs/smtp/settings/). |
| Webhooks | Your HTTPS endpoint | Real-time delivery, engagement and resource events. |
| MCP server | `https://api.emailit.com/mcp` | Letting AI assistants such as Claude, ChatGPT and Cursor work with your workspace. |
| OAuth 2.1 | `https://api.emailit.com/oauth/*` | Integrations that act on behalf of Emailit users without handling their API keys. |

Not sure whether to use the API or SMTP? Read [API or SMTP](/docs/get-started/api-or-smtp/).

## Base URL and versioning

All REST endpoints live under one base URL:

```text
https://api.emailit.com/v2
```

`v2` is the current and only documented version. The legacy `v1` API is deprecated; see [Versioning](/docs/api-reference/versioning/).

## Authentication

Send an API key as a bearer token in the `Authorization` header of every request:

```bash
curl https://api.emailit.com/v2/domains \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

- API keys start with `secret_`. Older keys without the prefix keep working.
- Each key belongs to one workspace and has a scope: **Full Access** (`full`) can call every endpoint, **Sending Only** (`sending`) can only send and manage sends. See [API keys](/docs/developers/api-keys/).
- OAuth access tokens issued to [OAuth apps](/docs/developers/oauth-apps/) are accepted in the same header.
- A missing key returns `401` with `API key required`, an unknown key returns `401` with `Invalid API key`, and a suspended workspace returns `403` with `Workspace is suspended`.

Never call the API from a browser or mobile app with your key. Keep it on your server. Details: [Authentication](/docs/api-reference/authentication/).

## IDs and prefixes

Every object has a string ID with a type prefix, so you can tell what an ID refers to at a glance.

| Object | Prefix | Example |
| --- | --- | --- |
| Email | `em_` | `em_4K6oASS7KP9ztzWmSN9ndEu13HW` |
| Sending domain | `dom_` | `dom_3xQ7mLp2RkT9vB4nHs8YcWd1Ze6` |
| API key | `key_` | `key_4F2kN8sQwE1rT6yU3iO9pA7sD5f` |
| Audience | `aud_` | `aud_3zR8tY2uI6oP4aS1dF9gH7jK5lM` |
| Subscriber | `sub_` | `sub_4K6oASS7KP9ztzWnqS4svxApJzO` |
| Contact | `con_` | `con_4A9sD2fG6hJ1kL8zX3cV7bN5mQw` |
| Template | `tem_` | `tem_3wE8rT1yU5iO9pA2sD6fG4hJ7kL` |
| Suppression | `sup_` | `sup_4K6oASS7KP9ztzWol5ElicOeKFE` |
| Webhook | `wh_` | `wh_3mN7bV2cX6zL9kJ4hG1fD8sA5pO` |
| Webhook request | `whr_` | `whr_4K6oASS7KP9ztzWpVUIec9Jneax` |
| Event | `evt_` | `evt_4K6oASS7KP9ztzWpqId2iIptac5` |
| Campaign | `cmp_` | `cmp_4B1nM5qW9eR3tY7uI2oP6aS8dF4` |
| Form | `frm_` | `frm_4C3vB7nM1qW5eR9tY2uI6oP8aS4` |
| Form submission | `fsub_` | `fsub_4K6oASS7KP9ztzWqvxLV3IsFRs8` |
| Automation | `aut_` | `aut_4D5fG9hJ3kL7zX1cV6bN2mQ8wE4` |
| Automation run | `aur_` | `aur_4K6oASS7KP9ztzWrWOjGgqompRo` |
| Email verification | `ev_` | `ev_4E7gH1jK5lZ9xC3vB8nM2qW6eR4` |
| Verification list | `evl_` | `evl_4F9hJ3kL7zX1cV5bN9mQ2wE6rT8` |
| DMARC report | `dmr_` | `dmr_4K6oASS7KP9ztzWsW7e5qkOYHO6` |

Domains created before the switch to `dom_` IDs can still have `sd_` or `sed_` IDs.

Some endpoints also accept a human-readable identifier in place of the ID: a name for API keys, domains, webhooks, campaigns and audiences, and an email address for contacts and suppressions. Emails, templates and events are looked up by ID only.

## Requests and responses

- **JSON in, JSON out.** Send request bodies as JSON with `Content-Type: application/json`. Malformed JSON returns `400` with `Invalid JSON in request body`. A request body can be up to 50 MB; an email's final MIME message can be up to 40 MB.
- **Errors.** Most errors return `{"statusCode", "error", "message"}`. Validation errors add a `details` array, and sending errors return `validation_errors`. Plan-gated features return `403` with `"error": "plan_required"`. See [Errors](/docs/api-reference/errors/).
- **Pagination.** List endpoints take `page` and `limit` (1 to 100) and return `data`, `next_page_url` and `previous_page_url`. Templates and automations use `page` and `per_page`. See [Pagination](/docs/api-reference/pagination/).
- **Filtering and sorting.** Filter with `field.condition=value`, combine filters with `match=all` or `match=or`, and sort with `order` and `direction`. For example, `GET /v2/emails?status.exact=bounced&order=created_at&direction=desc`. See [Filtering](/docs/api-reference/filtering/).
- **Idempotency.** Send an `Idempotency-Key` header on `POST /emails` and `POST /emails/:id/forward` to make retries safe. Emailit replays the first response for 24 hours. See [Idempotency](/docs/api-reference/idempotency/).
- **Rate limits.** Sending is limited per workspace, by default to 2 emails per second and 5,000 emails per day, shared between the API and SMTP. Responses include `ratelimit-*` headers, and a `429` includes `retry-after`. See [Rate limits](/docs/api-reference/rate-limits/) and [Limits](/docs/limits/).

## SDKs

Official libraries wrap the REST API for Node.js, PHP, Laravel, Python, Ruby, Go, Java, .NET and Rust. They all live on [GitHub](https://github.com/emailit). See [SDKs and libraries](/docs/sdks/) for install commands, and the framework guides for complete examples, starting with [Node.js](/docs/frameworks/nodejs/).

## Webhooks

Webhooks push events to your endpoint as they happen: deliveries, bounces, opens, clicks, inbound mail, and changes to domains, contacts and other resources. Each request carries a JSON array of up to 100 events and is signed with HMAC-SHA256 in the `X-Emailit-Signature` header. Failed requests are retried for up to 11 attempts. Start with [Set up a webhook](/docs/webhooks/set-up/) and [Request signature](/docs/webhooks/request-signature/).

## MCP server and AI tools

The hosted [MCP server](/docs/mcp/) at `https://api.emailit.com/mcp` gives AI assistants 109 tools covering the full API v2, from sending email to campaigns and automations. Assistants sign in with OAuth or an API key, and the [Emailit plugins](/docs/mcp/plugins-and-skills/) add skills for ChatGPT, Codex, Claude Code, Cursor and Grok.

The docs are also published for AI: every page has a Markdown version, and [/docs/llms.txt](/docs/developers/llms-txt/) indexes them all.

## Next steps

  - [Create an API key](/docs/developers/api-keys/): Choose a scope, restrict it to a domain and store it safely.
  - [Send your first email](/docs/quickstart/api/): Make your first API call in a few minutes.
  - [SDKs and libraries](/docs/sdks/): Official libraries for nine languages and frameworks.
  - [API reference](/docs/api-reference/): Every endpoint, parameter and response.

---
Source: https://emailit.com/docs/developers/
