> ## Documentation Index
> Fetch the complete documentation index at: https://docs.drin.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Simulate an inbound email

> POST /v1/inbound/simulate — run the full inbound pipeline in test mode without touching metrics, quotas, or billing.

Inject a fake inbound message that runs the real ingest pipeline — persisted to a thread and delivered to your webhooks — but is flagged test mode and excluded from metrics, quotas, and billing.

**`POST /v1/inbound/simulate`**

Use this to build and test receiving end to end before any MX record resolves. The message is synthesized, threaded, and pushed to your [webhooks](/webhooks) exactly like a real inbound email — the only difference is the row is marked `test_mode` so it never affects your numbers. The `to` address must belong to an [inbox](/api-reference/inboxes/create) on a receiving-enabled domain.

## Body

<ParamField body="to" type="string" required>
  The receive address the message is addressed to, for example `support@acme.com`. Must match an existing inbox.
</ParamField>

<ParamField body="from" type="object" required>
  The sender as `{ email, name? }`, for example `{ "email": "jordan@example.com", "name": "Jordan Lee" }`.
</ParamField>

<ParamField body="subject" type="string" required>
  The subject line of the synthesized message.
</ParamField>

<ParamField body="html" type="string">
  An HTML body. Provide `html`, `text`, or both.
</ParamField>

<ParamField body="text" type="string">
  A plain-text body. Provide `html`, `text`, or both.
</ParamField>

<ParamField body="headers" type="object">
  Extra raw headers to stamp on the synthesized message, as a string map.
</ParamField>

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.drin.run/v1/inbound/simulate \
    -H "Authorization: Bearer $DRIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "to": "support@acme.com",
      "from": { "email": "jordan@example.com", "name": "Jordan Lee" },
      "subject": "Where'"'"'s my order?",
      "text": "Hi — order #4821 still hasn'"'"'t shipped."
    }'
  ```

  ```typescript Node.js theme={null}
  import { DrinClient } from "@drin00/sdk";

  const drin = new DrinClient({ apiKey: process.env.DRIN_API_KEY });

  const result = await drin.inbound.simulate({
    to: "support@acme.com",
    from: { email: "jordan@example.com", name: "Jordan Lee" },
    subject: "Where's my order?",
    text: "Hi — order #4821 still hasn't shipped.",
  });

  console.log(result.messageId, result.threadId);
  ```
</CodeGroup>

## Response

`200 OK` — the ids of the synthesized message and its thread, plus the ids of any webhook deliveries the simulation fired. Fetch the conversation with [retrieve thread](/api-reference/threads/get).

```json theme={null}
{
  "messageId": "msg_01HZ9D8S3M",
  "threadId": "thr_01HZ9D8S3M",
  "webhookDeliveries": ["whd_01HZ9D9X5P"]
}
```

<Note>
  **Never counted.** Simulated inbound is invisible to metrics, send quotas, and billing. It exists purely to let you wire up and verify your receiving and webhook handling.
</Note>
