---
title: "Place an order paid from the wallet"
method: POST
path: "/api/agent/v1/orders"
---

# Place an order paid from the wallet

`POST /api/agent/v1/orders`

## Request

- Base URL: `https://essentras.com`
- URL: `https://essentras.com/api/agent/v1/orders`
- Auth: HTTP bearer

Requires orders:write. Spends real money from the prepaid wallet. All or nothing: the order, the wallet debit and the brief are written in one transaction, and nothing is bought if any outlet is unavailable (422 items_unavailable), the price changed (409 price_changed) or the balance is too low (402 insufficient_funds). Idempotency: the same Idempotency-Key with the same body replays the stored response with the header Idempotent-Replayed: true; the same key with a different body is 422 idempotency_key_reused; a concurrent duplicate with the same body is 409 idempotency_in_progress (until it finishes, at most 15 minutes; retry with the same key). A request refused before an order is paid releases the key. If anything fails after the order was paid, the key is kept: the response is 201 with the order, or 500 internal_error with order_may_exist true, and you retry with the SAME key to get the order back. Keys are kept for 24 hours. Always quote first and pass the quoted total as expected_total_usd.

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `items` object[], required
    - `id` string, required: Outlet id. Each outlet once per order; there is no quantity.
  - `expected_total_usd` number: The total from your quote. If the server total differs by a cent or more, nothing is bought.
  - `client_reference` string: Your own reference for this order.
  - `brief` Brief
    - `subject_name` string, required: Who or what the article is about.
    - `subject_title` string
    - `links` string, required: Must contain at least one real link.
    - `goal` string, required: The business and what the coverage should achieve.
    - `avoid` string
    - `title_ideas` string
    - `notes` string
    - `placement_notes` object[]: Optional per-outlet angle. Each id must be an outlet on the order.
      - `id` string, required
      - `note` string, required

## Response `201`

Order placed, or a replay of an earlier identical request (then the Idempotent-Replayed: true header is set)

- object
  - `object` 'order'
  - `id` string: Order id for the API (the public id).
  - `number` integer, nullable
  - `status` string
  - `payment_status` string
  - `fulfillment` 'awaiting_payment' | 'awaiting_brief' | 'in_progress' | 'partially_published' | 'published' | 'cancelled' | 'refunded'
  - `channel` 'api' | 'reseller_portal' | 'website'
  - `created_at` string, date-time
  - `paid_at` string, date-time, nullable
  - `currency` 'USD'
  - `pricing_basis` 'list' | 'reseller'
  - `subtotal` number
  - `discount` number
  - `discount_reason` string, nullable
  - `total` number
  - `paid_from_wallet` number
  - `client_reference` string, nullable
  - `line_items` object[]
    - `id` string: Outlet id.
    - `name` string
    - `type` string
    - `quantity` integer
    - `unit_price` number
    - `list_price` number
    - `amount` number
    - `placement_note` string, nullable
    - `status` 'in_progress' | 'published'
    - `live_url` string, uri, nullable
    - `published_at` string, date-time, nullable
  - `brief` object, nullable
    - `status` string
    - `submitted_at` string, date-time, nullable
    - `article_status` string
  - `dashboard_url` string, uri
  - `wallet` object
    - `available` number
    - `currency` string
  - `next_step` string

## Other responses

- `400`: invalid_json, idempotency_key_required, invalid_request, too_many_items, duplicate_item, quantity_unsupported or invalid_brief (with field)
- `401`: authentication_required, invalid_api_key, api_key_revoked or api_key_expired
- `402`: insufficient_funds, with total, available, shortfall and top_up_url. Nothing was ordered.
- `403`: insufficient_scope, ip_not_allowed, order_limit_exceeded or daily_limit_exceeded
- `409`: price_changed (with the fresh quote) or idempotency_in_progress
- `422`: items_unavailable (with unavailable[]), idempotency_key_reused or invalid_total
- `429`: rate_limited
- `500`: payment_failed (the wallet was not charged) or internal_error. internal_error with order_may_exist true means the order was paid: retry with the SAME Idempotency-Key to get it back.
- `503`: purchases_disabled. Ordering is paused; nothing was charged.

---

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