> ## Documentation Index
> Fetch the complete documentation index at: https://docs.taberna.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Taberna is a crypto payments API. Amounts are priced in fiat (USD or EUR) and paid in crypto.
> Fiat amounts are ALWAYS decimal strings ("9.99"), never numbers. Crypto amounts are integer strings in the asset's smallest unit.
> Authenticate merchant endpoints with `Authorization: Bearer tbrn_live_...`. Every key is bound to one store and carries an explicit scope set, so never pass a store id to a /v1 endpoint.
> A 401 means the credential is bad; a 403 means the key lacks a scope. Never retry or re-authenticate on a 403 — surface it as a configuration error.
> The /v1/checkouts endpoints are deliberately unauthenticated and run in the buyer's browser. Never send an API key to a browser.
> Verify webhook signatures over the RAW request body before parsing JSON, and treat delivery as at-least-once: handlers must be idempotent.
> Never grant value based on a browser redirect to successUrl. Fulfil on a signature-verified webhook, or on a server-side read of GET /v1/orders/{id} or GET /v1/invoices/{id}.
> There is no test mode: every payment method is a live chain moving real funds.
> A merchant can run an entire shop with no code: the dashboard creates products and invoices, and every store can host a storefront at {slug}.taberna.io with its own theme, sections, branding and optional custom domain. Never assume the reader has an API integration.
> Taberna issues no refunds and performs no KYC. A refund is something the merchant sends from their own payout wallet, off-platform.

# Request limits

> Body size, item counts, string lengths and page sizes, in one table.

Every hard bound the API enforces on a request. Exceeding one is a `400` with
`{ "error": "Invalid request data" }` unless the table says otherwise.

| Limit                      | Value                                                                                                          |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Request body               | **8 MiB** (8,388,608 bytes) — exceeded gives `413 { "error": "Payload too large" }`                            |
| Order line items           | 1 to 20                                                                                                        |
| Order item quantity        | 1 to 1,000,000                                                                                                 |
| Invoice line items         | 1 to 100                                                                                                       |
| Invoice item quantity      | 1 to 1,000,000                                                                                                 |
| `Idempotency-Key`          | 1 to 255 characters                                                                                            |
| `successUrl` / `cancelUrl` | 2048 characters, `http` or `https` only                                                                        |
| `memo`                     | 5000 characters                                                                                                |
| Invoice item `description` | 2000 characters                                                                                                |
| Stock append `text`        | 5,000,000 characters, and at most 10,000 lines per call — counted after repeats within the batch are collapsed |
| List `limit`               | 1 to 100, defaults to 20                                                                                       |
| Fiat decimal places        | 3                                                                                                              |

<Info>
  The 8 MiB cap is on **encoded bytes**, not characters. A stock-append `text` well
  under its 5,000,000-character limit can still `413` once non-ASCII content is UTF-8
  encoded. See [Appending stock](/build/products-api#appending-stock).
</Info>

## Expiry windows

| Window                  | Default    | Range                | Set by                                            |
| ----------------------- | ---------- | -------------------- | ------------------------------------------------- |
| Order                   | 30 minutes | 10 minutes – 90 days | `expiresIn` on `POST /v1/orders`                  |
| Invoice                 | 24 hours   | 10 minutes – 90 days | `expiresIn` on `POST /v1/invoices`, or a template |
| Payment attempt (quote) | 30 minutes | —                    | Not settable                                      |

## Invoice email limits

Emailing an invoice is rate-limited at three levels — per invoice, per store over a
rolling 24 hours, and platform-wide. A refusal is a `429` carrying `retryAfterSeconds`
and a matching `Retry-After` header when the block is a cooldown you can wait out.
Check `email.canSend` on the invoice rather than probing. Details in
[Emailing an invoice](/invoices-email).
