---
title: "Place an order — Anis Developers"
description: "Buys cards from a wallet, under an operation id you choose and keep. The same id sent again never buys twice: it resumes the same order."
url: https://developers.anis.ly/reference/create-order/
language: en
---

> Every page of this documentation: https://developers.anis.ly/llms.txt

[API reference](https://developers.anis.ly/reference.md) · Orders

# Place an order

`POST /v1/wallets/{walletId}/orders`

Buys cards from a wallet, under an operation id you choose and keep. The same id sent again never buys twice: it resumes the same order.

- **Permission:** `orders:create`
- **Authentication:** Signed order
- **Staff-set limits it counts toward:** All requests, Orders
- **.NET SDK:** `anis.Orders.CreateAsync(walletId, operationId, order)  /  ResumeAsync(...)`

- `201`: the order completed, and this answer carries the card codes. Store them first.
- `200`: the answer a resume receives when the first answer was lost. If it carries card codes, it is the first time you see them — store them.
- An answer marked `Idempotency-Replayed: true` repeats an order whose outcome was already sent: it carries the order, not the codes. If you never received that first answer — a timeout — the codes were in it: reveal them with the order’s invoice id, which needs `cards:reveal`.
- `202`: accepted, no outcome yet. Send the same order again after `Retry-After`.

## Parameters

| Name | In | Type | Notes |
| --- | --- | --- | --- |
| `walletId` (required) | `path` | UUID | A UUID, lower-case with hyphens. |

## Request

Signed with your key, with a one-time nonce, a digest of the body and your operation id as `Idempotency-Key`.

Headers: `Signature-Input`, `Signature`, `Content-Digest`, `Nonce`, `Idempotency-Key`, `X-Anis-Date`, `Accept-Language` (optional). The SDKs set all of them for you.

**Body:** [CreateOrderRequest](#type-createorderrequest), as JSON.

| Field | Type | Notes |
| --- | --- | --- |
| `externalReference` | string | Your own reference, 1 to 100 characters: Latin letters and digits, space and `- _ . : / #`. |
| `cardId` (required) | UUID | The catalogue card to buy. |
| `quantity` (required) | integer | At least 1 and at most the per-order maximum (100 by default), and within the card’s own minimum and maximum. |
| `expectedUnitPrice` (required) | [Money](#type-money) | The card’s `unitPrice` exactly as the catalogue showed it for this wallet. |
| `expectedTotal` (required) | [Money](#type-money) | `expectedUnitPrice` times `quantity`, exactly — computed without floating point. |
| `useAllowedDebt` | boolean | Set to `true` only if you consent to use the account’s allowed debt. Defaults to `false` and is never switched on for you. |

## Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | Success. | [Order](#type-order) |
| 201 | The order completed. | [Order](#type-order) |
| 202 | Accepted — no outcome yet. | [Order](#type-order) |
| 401 | Refused: not authenticated. | [Problem](#refusals) |
| 402 | Refused: needs consent to use allowed debt. | [Problem](#refusals) |
| 403 | Refused: not allowed. | [Problem](#refusals) |
| 404 | Refused: not found, or not yours. | [Problem](#refusals) |
| 409 | Refused: conflicts with the current state. | [Problem](#refusals) |
| 422 | Refused: the request breaks a rule. | [Problem](#refusals) |
| 429 | Refused: a limit was reached. | [Problem](#refusals) |
| 503 | No decision: a dependency was unavailable. | [Problem](#refusals) |

Every answer is signed by Anis; the SDKs check it before you see it.

## Refusals

Every refusal is a signed problem. Branch on its `code`; each links to what it means and what to do.

| Error | Code | Status |
| --- | --- | --- |
| [Invalid credentials](https://developers.anis.ly/errors/invalid-credentials.md) | `invalid_credentials` | 401 |
| [Insufficient scope](https://developers.anis.ly/errors/insufficient-scope.md) | `insufficient_scope` | 403 |
| [Source address not allowed](https://developers.anis.ly/errors/source-ip-not-allowed.md) | `source_ip_not_allowed` | 403 |
| [Rate limited](https://developers.anis.ly/errors/rate-limited.md) | `rate_limited` | 429 |
| [Replay detected](https://developers.anis.ly/errors/replay-detected.md) | `replay_detected` | 409 |
| [Account not authorised](https://developers.anis.ly/errors/binding-not-authorized.md) | `binding_not_authorized` | 403 |
| [Account inactive](https://developers.anis.ly/errors/account-inactive.md) | `account_inactive` | 403 |
| [Wallet not granted](https://developers.anis.ly/errors/wallet-not-granted.md) | `wallet_not_granted` | 404 |
| [Not found](https://developers.anis.ly/errors/resource-not-found.md) | `resource_not_found` | 404 |
| [Validation failed](https://developers.anis.ly/errors/validation-failed.md) | `validation_failed` | 422 |
| [Currency not supported](https://developers.anis.ly/errors/currency-not-supported.md) | `currency_not_supported` | 422 |
| [Operation id already used](https://developers.anis.ly/errors/idempotency-conflict.md) | `idempotency_conflict` | 409 |
| [Allowed-debt consent required](https://developers.anis.ly/errors/allowed-debt-consent-required.md) | `allowed_debt_consent_required` | 402 |
| [Insufficient balance](https://developers.anis.ly/errors/insufficient-balance.md) | `insufficient_balance` | 409 |
| [Purchase not allowed](https://developers.anis.ly/errors/purchase-not-allowed.md) | `purchase_not_allowed` | 403 |
| [Order refused](https://developers.anis.ly/errors/order-refused.md) | `purchase_not_allowed` | 409 |
| [Business subscription required](https://developers.anis.ly/errors/business-subscription-required.md) | `business_subscription_required` | 409 |
| [Wallet disabled](https://developers.anis.ly/errors/wallet-disabled.md) | `wallet_disabled` | 409 |
| [Wallet expired](https://developers.anis.ly/errors/wallet-expired.md) | `wallet_expired` | 409 |
| [Card unavailable](https://developers.anis.ly/errors/card-unavailable.md) | `card_unavailable` | 409 |
| [Quantity unavailable](https://developers.anis.ly/errors/quantity-unavailable.md) | `quantity_unavailable` | 409 |
| [Price changed](https://developers.anis.ly/errors/price-changed.md) | `price_changed` | 409 |
| [Spending allowance used up](https://developers.anis.ly/errors/owner-limit-exceeded.md) | `owner_limit_exceeded` | 409 |
| [Daily limit reached](https://developers.anis.ly/errors/daily-limit-exceeded.md) | `daily_limit_exceeded` | 429 |
| [Service unavailable](https://developers.anis.ly/errors/dependency-unavailable.md) | `dependency_unavailable` | 503 |
| [Request timeout](https://developers.anis.ly/errors/request-timeout.md) | `request_timeout` | 504 |
| [Internal error](https://developers.anis.ly/errors/internal-error.md) | `internal_error` | 500 |

## Types

### CreateOrderRequest

| Field | Type | Notes |
| --- | --- | --- |
| `externalReference` | string | Your own reference, 1 to 100 characters: Latin letters and digits, space and `- _ . : / #`. |
| `cardId` (required) | UUID | The catalogue card to buy. |
| `quantity` (required) | integer | At least 1 and at most the per-order maximum (100 by default), and within the card’s own minimum and maximum. |
| `expectedUnitPrice` (required) | [Money](#type-money) | The card’s `unitPrice` exactly as the catalogue showed it for this wallet. |
| `expectedTotal` (required) | [Money](#type-money) | `expectedUnitPrice` times `quantity`, exactly — computed without floating point. |
| `useAllowedDebt` | boolean | Set to `true` only if you consent to use the account’s allowed debt. Defaults to `false` and is never switched on for you. |

### Money

| Field | Type | Notes |
| --- | --- | --- |
| `amount` (required) | string | A decimal string with exactly three decimals, such as `"10.500"` — never a JSON number. |
| `currency` (required) | string | The currency code, such as `LYD`: always the wallet’s currency. |
| `asOf` | string (date-time) | When this price or balance was read. |

### Order

| Field | Type | Notes |
| --- | --- | --- |
| `operationId` (required) | UUID | The operation id you chose and sent as `Idempotency-Key`. |
| `status` (required) | string | `processing`: accepted, no outcome yet. `completed`: bought. `failed`: refused by a business rule, nothing bought. `recoveryExhausted`: Anis could not learn the outcome yet — it may have completed; keep resuming slowly and tell Anis. Values: `processing`, `recoveryExhausted`, `completed`, `failed` |
| `invoiceId` | UUID | The invoice the cards are on. Use it to reveal them again later. |
| `walletId` | UUID | The wallet the order was paid from. |
| `cardId` | UUID | The catalogue card bought. |
| `quantity` | integer | How many cards. |
| `total` | [Money](#type-money) | What the order cost. |
| `soldCards` | list of [RevealedCredential](#type-revealedcredential) | The card codes. Present only on the answer that FIRST reports the order completed — store them before anything else. |
| `completedAt` | string (date-time) | When the order completed. |

### RevealedCredential

| Field | Type | Notes |
| --- | --- | --- |
| `soldCardId` (required) | UUID | The sold card these codes belong to. |
| `serialNumber` | string | The card’s serial number. A secret: store it where you keep secrets and never log it. |
| `voucher` | string | The card’s voucher code. A secret: store it where you keep secrets and never log it. |
| `revealedAt` | string (date-time) | When it was revealed. |
