---
title: "Ingest a canonical EmailInboundEvent for the given thread. Bypasses the vendor webhook; used by sandbox / replay / direct integrators."
method: POST
path: "/v1/email/threads/{thread_id}"
tags: ["email"]
---

# Ingest a canonical EmailInboundEvent for the given thread. Bypasses the vendor webhook; used by sandbox / replay / direct integrators.

`POST /v1/email/threads/{thread_id}`

Canonical ingest endpoint.

The path's ``{thread_id}`` and the body's
``event.provider_thread_id`` must match — defense against
accidentally (or maliciously) posting an event whose body claims a
different thread than the URL.

## Path parameters

- `thread_id` string, required

## Request body

- IngestEmailThreadRequest — Canonical ingest body. The path's ``{thread_id}`` MUST match ``event.provider_thread_id`` — the route enforces this so a caller can't bury a different thread id inside the body. Likewise ``event.organization_id`` must match the caller's org from the auth dependency.
  - `event` EmailInboundEvent, required — Canonical inbound email envelope. Produced by the canonicalizer (ENG-416) from a Nylas inbound payload (Gmail or Microsoft 365). Provider-agnostic: every provider collapses to this shape above the connector boundary. ``received_idempotency_key`` is a deterministic SHA-256 of ``(account_id, provider_message_id)`` so webhook redelivery is idempotent at the persistence layer.
    - `organization_id` string, uuid, required
    - `account_id` string, uuid, required
    - `provider` 'gmail' | 'microsoft', required — Mailbox-native providers we connect to via Nylas in v1. Both providers ride the same `MailboxConnector` (Nylas implementation). Pattern B (brand-domain transactional sending: SendGrid / SES / Resend) is v2 and lives in a separate connector.
    - `provider_thread_id` string, required
    - `provider_message_id` string, required
    - `rfc822_message_id` string, required
    - `in_reply_to` string, nullable
    - `references` string[]
    - `from` EmailAddress, required — A single RFC 5321 mailbox + optional display name.
      - `address` string, required
      - `name` string, nullable
    - `to` EmailAddress[]
      - `address` string, required
      - `name` string, nullable
    - `cc` EmailAddress[]
      - `address` string, required
      - `name` string, nullable
    - `reply_to` EmailAddress[]
      - `address` string, required
      - `name` string, nullable
    - `subject` string, required
    - `body_text` string, nullable
    - `body_html` string, nullable
    - `headers` array[]
      - unknown[]
        - unknown
    - `attachments` WireAttachment[]
      - `storage_object_id` string, uuid, required
      - `filename` string, required
      - `content_type` string, required
      - `size_bytes` integer, required
      - `disposition` 'inline' | 'attachment'
      - `content_id` string, nullable
    - `auth_results` WireAuthResults — SPF / DKIM / DMARC results from the receiving MTA.
      - `spf` string, nullable
      - `dkim` string, nullable
      - `dmarc` string, nullable
    - `mime_size_bytes` integer, nullable
    - `raw_storage_object_id` string, uuid, nullable
    - `received_at` string, date-time, required
    - `received_idempotency_key` string, required

## Response `200`

Successful Response

- IngestEmailThreadResponse — Thin surface over ``CanonicalizerResult``. ``outcome`` collapses the canonicalizer's decision plus the "duplicate" sentinel the Redis replay-dedup gate emits when the same ``provider_message_id`` has already been processed.
  - `outcome` 'reply' | 'observe' | 'archive' | 'drop' | 'duplicate', required
  - `reason` string, nullable
  - `session_id` string, uuid, nullable
  - `user_turn_id` string, uuid, nullable
  - `assistant_turn_id` string, uuid, nullable
  - `draft_id` string, uuid, nullable
  - `auto_dispatched` boolean

## Other responses

- `400` — Bad request
- `401` — Authentication required
- `422` — Validation Error

---

[API](https://skmtc.net/oneloop-hq/apis/feather-api.md) · [All operations](https://skmtc.net/oneloop-hq/apis/feather-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/oneloop-hq/feather-api/versions/888bdd5c076e/schema)
