---
title: "Simulate a received email (test keys only)"
method: POST
path: "/v1/emails/received/simulate"
tags: ["Emails"]
---

# Simulate a received email (test keys only)

`POST /v1/emails/received/simulate`

## Request

- Base URL: `https://api.honkio.ca`
- URL: `https://api.honkio.ca/v1/emails/received/simulate`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Requires `emails:w`.

## Request body

- object: A message to receive as if it had arrived by email, run through the same processing, record and email.received webhook as real mail.
  - `from` string, email, required: The sender's address.
  - `to` string[], required: Up to 10 recipients, each your test managed address or an address at one of your test mode domains.
  - `cc` string[]: Up to 10 more recipients, with the same rule as to.
  - `subject` string: Up to 998 characters.
  - `text` string: The plain text body.
  - `html` string: The HTML body.
  - `attachments` object[]: Up to 10 files, 10 MB in total.
    - `filename` string, required: The file name.
    - `content_type` string, required: The MIME type, such as application/pdf.
    - `content` string, required: The file, base64 encoded.
    - `content_id` string: A Content-ID, so html can reference the file as cid:.
    - `inline` boolean: Mark the file inline rather than attached.
  - `verdicts` object: The spam, virus and authentication verdicts to record. virus FAIL stores the message as rejected, as real mail would be.
    - `spf` 'PASS' | 'FAIL' | 'GRAY' | 'PROCESSING_FAILED': The verdict to record. Left out, it is PASS.
    - `dkim` 'PASS' | 'FAIL' | 'GRAY' | 'PROCESSING_FAILED': The verdict to record. Left out, it is PASS.
    - `dmarc` 'PASS' | 'FAIL' | 'GRAY' | 'PROCESSING_FAILED': The verdict to record. Left out, it is PASS.
    - `spam` 'PASS' | 'FAIL' | 'GRAY' | 'PROCESSING_FAILED': The verdict to record. Left out, it is PASS.
    - `virus` 'PASS' | 'FAIL' | 'GRAY' | 'PROCESSING_FAILED': The verdict to record. Left out, it is PASS.
  - `in_reply_to` string: The Message-ID this message replies to, for threading.
  - `headers` object[]: Up to 20 extra headers.
    - `name` string, required: The header name.
    - `value` string, required: The header value.

## Response `201`

The simulated message, in the same shape GET /v1/emails/received/:id answers with. livemode is always false.

- object: The simulated message, in the same shape GET /v1/emails/received/:id answers with. livemode is always false.
  - `id` string, required
  - `from` string, required
  - `from_name` string, nullable, required
  - `to` string[], required
  - `cc` string[], required
  - `subject` string, required
  - `message_id` string, nullable, required
  - `in_reply_to` string, nullable, required
  - `received_at` string, date-time, required
  - `status` 'received' | 'rejected', required
  - `reject_reason` string, nullable, required: Why a rejected message was stored headers only and uncharged: virus, daily_cap (the daily message cap), daily_mb_cap (the daily cap on billable MB), or insufficient_balance (the balance could not cover its charge). Null for a received message.
  - `verdicts` object, required
    - `spf` string, required
    - `dkim` string, required
    - `dmarc` string, required
    - `spam` string, required
    - `virus` string, required
  - `attachments_count` integer, required
  - `size_bytes` integer, required
  - `charge_millicents` integer, required
  - `domain_id` string, nullable, required
  - `livemode` boolean, required
  - `text` string, nullable, required
  - `html` string, nullable, required
  - `html_format` 'cid' | 'links' | 'sanitized', required
  - `remote_images` integer, nullable, required: Remote images parked in data-remote-src by html_format=sanitized; null for the other formats.
  - `headers` object[], required
    - `name` string, required
    - `value` string, required
  - `references` string[], required
  - `reply_to` string[], required
  - `envelope_recipients` string[], required
  - `body_purged` boolean, required
  - `body_truncated` boolean, required: text or html was cut at 2 MB (UTF-8 bytes) when stored; the raw message keeps it whole.
  - `raw_available` boolean, required
  - `parse_failed` boolean, required
  - `attachments_bytes` integer, required: Total size of the attachments, in bytes.
  - `attachments` object[], required
    - `id` string, required
    - `filename` string, required
    - `content_type` string, required
    - `content_id` string, nullable, required
    - `inline` boolean, required
    - `size_bytes` integer, required
    - `expires_at` string, date-time, required

## Other responses

- `401`: Missing, invalid, revoked or expired API key.
- `402`: The account has no balance, or a LIVE key was used before the first top-up.
- `403`: TEST_KEY_REQUIRED: this endpoint only accepts test keys.
- `422`: VALIDATION_ERROR (bad input, or attachments over 10 MB total) or SIMULATE_RECIPIENT_NOT_OWNED (a to/cc address is neither the account's test managed address nor one of its own test-mode domains).
- `429`: TEST_EMAIL_QUOTA_EXCEEDED: the account has simulated 200 received emails in the last 24 hours, counted apart from test sends (details carry direction inbound, limit, used, requested and window_hours). Or RATE_LIMITED at 100 requests per second.
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/honkio/apis/honkio-api.md) · [All operations](https://skmtc.dev/honkio/apis/honkio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/honkio/apis/honkio-api/revisions/ce4ed3fe9691?raw)
