# Quickstart

From no account to a delivered email: create a key and make your first send.

### Create an account

If you don't already have an organization, [create an account](https://app.e-comms.dev)
— it's free to start, and everything you create inside it (members, templates, API keys)
lives within that organization.

### Create an API key

From **Settings → API keys**, create a key with the *Send messages* permission. The
**Create key** button shows you the token exactly once — copy it right then. The
[authentication guide](/en/docs/get-started/authentication) has the full detail, with
screenshots of the panel.

### Send your first email

The public surface — the only part of the API an external integrator calls — lives under
`/v1` and reads the organization from the key itself, not from the URL. `from` has to name a
sender already registered in your organization — the address you signed up with is already
one, verified from the moment your account was created, so it works here with nothing further
to set up:

```bash
curl -X POST https://api.e-comms.dev/v1/email \
  -H "Authorization: Bearer ek_live_<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotencyKey": "quickstart-2026-09-19",
    "to": ["you@example.com"],
    "from": "you@example.com",
    "content": {
      "type": "raw",
      "subject": "My first email",
      "html": "<p>It works!</p>",
      "text": "It works!"
    }
  }'
```

```js
const response = await fetch("https://api.e-comms.dev/v1/email", {
  method: "POST",
  headers: {
    Authorization: "Bearer ek_live_<your-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    idempotencyKey: "quickstart-2026-09-19",
    to: ["you@example.com"],
    from: "you@example.com",
    content: {
      type: "raw",
      subject: "My first email",
      html: "<p>It works!</p>",
      text: "It works!",
    },
  }),
})

const body = await response.json()
```

```python
import requests

response = requests.post(
    "https://api.e-comms.dev/v1/email",
    headers={"Authorization": "Bearer ek_live_<your-key>"},
    json={
        "idempotencyKey": "quickstart-2026-09-19",
        "to": ["you@example.com"],
        "from": "you@example.com",
        "content": {
            "type": "raw",
            "subject": "My first email",
            "html": "<p>It works!</p>",
            "text": "It works!",
        },
    },
)

body = response.json()
```

Sending from a different address — your own domain, once you've verified it — is a matter of
registering a new sender in **Settings → Sending**, no code change here.

### Confirm it was sent

A `202` response means the email was admitted — not that it has arrived yet. Each addressee
shows up with its own outcome in `results`:

```json
{
  "results": [
    {
      "address": "you@example.com",
      "messageId": "01a0ba31-3fe4-7cc4-a1c6-64bdaaa5d99c",
      "status": "claimed"
    }
  ]
}
```

`claimed` is the only status this response can carry — the provider has not been called yet
when it is built. Keep the `messageId`: it is what you
[retrieve](/en/docs/messaging/email/retrieve) to learn whether the send actually arrived, and
what correlates a [webhook](/en/docs/reference/webhooks) event with this same email. An error
carries a `code` from a closed set — check the
[error reference](/en/docs/reference/errors) to see which code answers which situation.
