---
title: "Send an email card"
method: POST
path: "/api/v1/review/{id}/send"
tags: ["API Reference"]
---

# Send an email card

`POST /api/v1/review/{id}/send`

## Request

- Base URL: `https://revnu.com`
- URL: `https://revnu.com/api/v1/review/{id}/send`
- Auth: HTTP bearer

Approve and send an email draft or reply Revnu wrote, optionally with an edited reply body. This sends real email.

Requires the `review:write` scope.

**Response.** `200 { "ok": true, "data": { "outcome": "sent", "queued": false, "messageId": "<id>" } }` once the provider accepted it; `messageId` is the delivery receipt. When the mailbox paces its sending, the email is queued instead: `data` has `queued: true` and, once the queue has placed it, `leavesAt` (ISO 8601) and `timing`. A provider refusal is also a `200`, as `{ "ok": false, "error": { "kind", "detail" } }`; `kind` is one of `rate_limited`, `out_of_credits`, `not_found`, `network`, `upstream_5xx`, `schema_drift`, `bad_input`, `missing_key` or `budget_exhausted`. The full shape is in [/openapi.json](/openapi.json). `409` if the card was already handled or is not an email card. `503 delivery_pending` with a `Retry-After` header if the provider's answer was lost: the send is fenced for reconciliation rather than risked twice, so wait and retry the same call. `503 unavailable`, also with `Retry-After`, when the delivery service could not be reached.

## Path parameters

- `id` string, required

## Request body

- object

## Response `200`

200 { "ok": true, "data": { "outcome": "sent", "queued": false, "messageId": "<id>" } } once the provider accepted it; messageId is the delivery receipt. When the mailbox paces its sending, the email is queued instead: data has queued: true and, once the queue has placed it, leavesAt (ISO 8601) and

- union
  - object
    - `ok` false, required
    - `error` OutreachError, required
      - `kind` 'bad_input' | 'budget_exhausted' | 'missing_key' | 'network' | 'not_found' | 'out_of_credits' | 'rate_limited' | 'schema_drift' | 'upstream_5xx', required
      - `detail` string, required
      - `retryAfterSec` number
      - `provider` string
    - `usage` ProviderUsage
      - `provider` string, required
      - `operation` string, required
      - `calls` number, required
      - `creditsUsed` number
      - `costUsd` number
      - `attempts` string[]
  - object
    - `ok` true, required
    - `data` object, required
      - `outcome` 'awaiting_approval' | 'held' | 'queued' | 'sent'
      - `queued` boolean, required
      - `alreadySent` boolean
      - `alreadyQueued` boolean
      - `messageId` string
      - `threadId` string
      - `deduped` boolean
      - `draftId` string
      - `review_item_id` string
      - `reviewItemId` string
      - `approvedBy` 'customer' | 'sequence' | 'setting'
      - `leavesAt` string
      - `timing` string
      - `sendsAtLocal` string
      - `shipsAt` number
      - `sendAtLocal` string
      - `detail` string
    - `usage` ProviderUsage
      - `provider` string, required
      - `operation` string, required
      - `calls` number, required
      - `creditsUsed` number
      - `costUsd` number
      - `attempts` string[]

## Other responses

- `400`: The request is malformed; the error names the problem.
- `401`: Missing, malformed, unknown or revoked token.
- `402`: `setup_pending`: the account hasn't started its trial. Finish setup with `GET /setup`.
- `403`: The token lacks the scope in `requiredScope`.
- `404`: Unknown id, or another account's id.
- `409`: A settled refusal: `invalid_action` (see `actions`) or `rejected`.
- `429`: Rate limited.
- `503`: Temporarily unavailable; retry the same call.

---

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