> ## Documentation Index
> Fetch the complete documentation index at: https://pigeonpost-developer.27communication.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Create your account, get your DSN and access token, and make your first calls.

## How to test? Create an account

To access the API and try its email features, follow these steps:

1. **Sign up** for PigeonPost. We create your **workspace**, with its own API server, database and **dashboard**.
2. **Log in to your dashboard and get your DSN.** Your DSN is your workspace's API address, for example `https://mail-api.example.com`. Use it for every request: `https://mail-api.example.com/api/v1/...`
3. **Generate an access token.** In the dashboard, open **API keys** and create one. It's shown only once, so copy it right away. Send it in the `X-API-KEY` header.
4. **Connect an email account.** In the dashboard, open **Accounts → Add account** and connect a mailbox with an email address and password (for Gmail use an [app password](/accounts/gmail)). It then appears under **Accounts**, so you can test API calls without building the connection flow first.
5. **Try the API.** Open the **API reference** tab, enter your DSN and access token, pick a route, fill in the parameters and send the request. No code needed.

## Your first calls

Set your DSN and access token as environment variables for the examples below:

```bash theme={null}
export EE_URL=https://mail-api.example.com   # your DSN
export EE_KEY=ee_your_access_token
```

Check that they work, and find the account you connected in the dashboard:

```bash theme={null}
curl "$EE_URL/api/v1/accounts" -H "X-API-KEY: $EE_KEY"
```

```json Response theme={null}
{
  "object": "Accounts",
  "data": [
    {
      "object": "Account",
      "id": "acc_ba1fa6938d8548298e8ce62e4b4b4e99",
      "user_id": "ana@acme.com",
      "name": "ana@acme.com",
      "provider": "imap",
      "status": "running",
      "status_detail": "",
      "is_locked": false,
      "metadata": {},
      "connection_params": {
        "mail": {
          "imap_host": "imap.acme.com", "imap_port": 993, "imap_user": "ana@acme.com", "imap_encryption": "SSL",
          "smtp_host": "smtp.acme.com", "smtp_port": 465, "smtp_user": "ana@acme.com", "smtp_encryption": "SSL"
        }
      },
      "created_at": "2026-10-06T09:01:28Z",
      "last_synced_at": "2026-10-06T09:15:02Z"
    }
  ],
  "has_more": false
}
```

Every id starts with its type: `acc_` for an account, `email_` for an email, and so on. See [Core concepts](/concepts#ids).

## Connect your users' accounts from your app

<Steps>
  <Step title="Connect the user's mailbox">
    Show a form in your app where the user enters their email address and password (an [app password](/accounts/gmail) for Gmail). Send them to the engine:

    ```bash theme={null}
    curl -X POST "$EE_URL/api/v1/auth/intent" \
      -H "X-API-KEY: $EE_KEY" -H "Content-Type: application/json" \
      -d '{
        "provider": "imap",
        "email": "ana@gmail.com",
        "password": "abcdefghijklmnop",
        "state": "user-42"
      }'
    ```

    For Gmail, Yahoo, iCloud and other [well-known providers](/accounts/imap#common-providers), the servers are filled in for you. For other mailboxes, also send the IMAP and SMTP servers. The engine signs in to both servers before saving the account.

    ```json Response 201 theme={null}
    {
      "object": "Account",
      "id": "acc_ba1fa6938d8548298e8ce62e4b4b4e99",
      "user_id": "ana@gmail.com",
      "name": "ana@gmail.com",
      "provider": "imap",
      "status": "running",
      "status_detail": "",
      "is_locked": false,
      "metadata": {},
      "connection_params": {
        "mail": {
          "imap_host": "imap.gmail.com", "imap_port": 993, "imap_user": "ana@gmail.com", "imap_encryption": "SSL",
          "smtp_host": "smtp.gmail.com", "smtp_port": 465, "smtp_user": "ana@gmail.com", "smtp_encryption": "SSL"
        }
      },
      "created_at": "2026-10-06T09:01:28Z",
      "last_synced_at": null
    }
    ```

    Save the account's `id` with your user. `state` is your own value, for example your user's id. If you have a webhook endpoint for `account.add`, it also receives the new account with your `state`. A wrong password answers `401 errors/invalid_credentials`: see [Connect a mailbox](/accounts/imap) for every setting and error.
  </Step>

  <Step title="List the user's emails">
    The account syncs every email that arrives from now on. Mail already in the mailbox isn't imported (unless you turn on [initial sync](/accounts/initial-sync), up to the last 30 days), so send it a test email first.

    ```bash theme={null}
    curl "$EE_URL/api/v1/emails?account_id=acc_ba1fa6938d8548298e8ce62e4b4b4e99&folder=INBOX&limit=20" \
      -H "X-API-KEY: $EE_KEY"
    ```

    ```json Response (shortened) theme={null}
    {
      "object": "Emails",
      "data": [
        {
          "object": "Email",
          "id": "email_94a0d77db739407e932c3b97fef44aac",
          "account_id": "acc_ba1fa6938d8548298e8ce62e4b4b4e99",
          "subject": "Quarterly report",
          "from_attendee": { "display_name": "Ana Lee", "identifier": "ana@example.com" },
          "date": "2026-10-06T09:12:00Z",
          "unread": true,
          "has_attachments": true,
          "origin": "external"
        }
      ],
      "has_more": true,
      "cursor": "eyJkIjoiMjAyNi0xMC0wNlQwOToxMjowMFoiLCJpIjoiOTRhMGQ3N2QifQ"
    }
    ```
  </Step>

  <Step title="Send an email">
    ```bash theme={null}
    curl -X POST "$EE_URL/api/v1/emails" \
      -H "X-API-KEY: $EE_KEY" -H "Content-Type: application/json" \
      -d '{
        "account_id": "acc_ba1fa6938d8548298e8ce62e4b4b4e99",
        "to": [{ "display_name": "Ana Lee", "identifier": "ana@example.com" }],
        "subject": "Hello from my app",
        "body": "<p>Sent through PigeonPost.</p>"
      }'
    ```

    ```json Response 201 theme={null}
    { "object": "EmailSent", "account_id": "acc_ba1fa6938d8548298e8ce62e4b4b4e99", "message_id": "84c3db9476d84b288bc6fa055a576764@mail-api.example.com", "provider_id": null, "tracking_id": null }
    ```

    The email is sent from the user's own address, through their provider.
  </Step>

  <Step title="Receive webhooks">
    Register a URL of your app, and choose the events it receives:

    ```bash theme={null}
    curl -X POST "$EE_URL/api/v1/webhooks/endpoints" \
      -H "X-API-KEY: $EE_KEY" -H "Content-Type: application/json" \
      -d '{
        "url": "https://app.example.com/webhooks/email",
        "trigger_events": ["email.new", "account.add", "account.status.disconnected"]
      }'
    ```

    Keep the `secret` from the response: it signs every call. When an email arrives, your URL receives an `email.new` event with the full email in `data.email`. See [Events](/webhooks/events) and [Verify signatures](/webhooks/signatures).
  </Step>
</Steps>

## What's next

<CardGroup cols={2}>
  <Card title="Replies and threads" icon="reply" href="/emails/replies-and-threads">
    Answer emails so they stay in the same conversation.
  </Card>

  <Card title="Attachments" icon="paperclip" href="/emails/attachments">
    Download received files and send your own.
  </Card>

  <Card title="Account status" icon="signal" href="/accounts/status">
    Handle expired passwords and revoked access.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/reference/errors">
    What each error means and how to handle it.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.