---
title: "Create eSIM order with USDT payment intent (auth + purchase scope)"
method: POST
path: "/api/v1/orders"
---

# Create eSIM order with USDT payment intent (auth + purchase scope)

`POST /api/v1/orders`

## Request

- Base URL: `https://roamzy.io`
- URL: `https://roamzy.io/api/v1/orders`
- Auth: HTTP bearer

Reserves an eSIM and creates a NowPayments invoice. Runs spending-limit gate (daily/monthly/cool-off/big-txn). Returns pay_url for the user to complete payment.

## Request body

- object
  - `country_slug` string, required
  - `amount_usdt` integer, required: Whole USDT. Anti-dust minimum is 20; smaller amounts are rejected with error "below_min_topup".
  - `pay_currency` string: Pay-currency code from GET /api/v1/payment-options. Ask the user which stablecoin + network they hold and pass their choice — do not guess. If omitted, the invoice falls back to usdttrc20 (USDT on TRON), which locks NowPayments checkout to that one network.

## Response `200`

Order created — user pays at pay_url. msisdn is the user-facing eSIM identifier; all other IDs are internal plumbing.

- object
  - `msisdn` string, nullable: USER-FACING eSIM phone number (e.g. "2040400002"). Show this to the human; hide the other IDs.
  - `order_id` string: Internal — pass to follow-up endpoints only.
  - `intent_id` string: Internal — use as :id in GET /api/v1/orders/:id. Do NOT show to user.
  - `esim_id` string: Internal — use as :id in GET /api/v1/esims/:id. Do NOT show to user.
  - `display_id` string: Internal short ID. Do NOT show to user.
  - `pay_url` string, uri: NowPayments hosted invoice. Surface to user.
  - `amount_usdt` number
  - `status` string
  - `user_facing` object: Pre-formatted UX hint — agents can copy identifier_value + action_url straight into user-visible text.
    - `identifier_label` string
    - `identifier_value` string, nullable: The MSISDN — same value as the top-level `msisdn` field.
    - `action_label` string
    - `action_url` string, uri
    - `hint` string
  - `next_steps` string[]

## Other responses

- `400`: Invalid body
- `402`: Spending limit exceeded (daily/monthly/cool-off)
- `403`: Purchase scope missing or big-txn confirmation required
- `404`: Country not in catalog
- `409`: eSIM cap reached or reservation conflict
- `502`: Upstream failure. `invoice_create_failed` — NowPayments could not create the invoice (retry with backoff). `provider_error` — the eSIM reservation step failed, before any invoice existed.
- `503`: Purchases paused (`purchases_paused`), site-wide payments off (`payments_disabled`) or unconfigured (`payments_not_configured`). Poll /api/v1/status and back off.

---

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