> ## 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.

# Conventions

> Base URL, money formats, timestamps, resource ids and the error shape — the rules that hold everywhere.

These hold everywhere in the API, in both directions. Every other Build page assumes
them rather than restating them.

## Base URL

```
https://api.taberna.io
```

Programmatic endpoints live under the versioned `/v1` prefix. The buyer-facing hosted
pages live on a separate host, and Taberna returns their full URLs (`checkoutUrl` for
orders, `url` for invoices) when you create the resource — never construct them
yourself.

## Money

| Kind               | Format                                                                                                                              |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| **Fiat amounts**   | Human decimal strings, never numbers — `"50"`, `"9.99"`. Up to 3 decimal places, no trailing-zero padding, so `"50"` means \$50.00. |
| **Crypto amounts** | Integer strings in the asset's smallest unit — wei, lamports, token base units. `"50010000"` is 50.01 USDC (6 decimals).            |

<Info>
  Do not parse either into a float for arithmetic. Use a decimal library or integer
  minor units. `"50"` means fifty, not fifty cents, and crypto amounts do not all
  have 18 decimals.
</Info>

Fiat pricing currencies are **`usd`** and **`eur`**. Nothing else is accepted.

## Timestamps

ISO-8601, UTC — `"2026-07-09T12:30:00.000Z"`. Query parameters that take a timestamp
(`createdAfter`, `createdBefore`) accept a `Z` or an explicit offset.

## Resource ids

Two kinds, and they are not interchangeable.

* **Public short ids** address orders and invoices: 21 or 22 **base58** characters, like
  `CcvnKdAXzvW8h3JaS1VJe`. This is the value that appears in checkout links, the value
  every webhook carries as `data.id`, and the value every `/v1` path parameter takes for
  those two resources.
* **UUIDs** address products, stores and webhook deliveries.

<Info>
  Short ids are validated against the base58 pattern **before any lookup runs**, on
  every route that takes one. A malformed short id is therefore
  `400 { "error": "Invalid request data" }`, not a `404`. See
  [Errors](/build/errors#validation-failures-are-always-the-same-400).
</Info>

## Errors

Every non-2xx response carries the same body:

```json theme={"dark"}
{ "error": "A human-readable message" }
```

There is one documented exception: [the invoice-send
endpoint](/invoices-email#the-rate-limit-envelope) adds `code` and `retryAfterSeconds`.
Full detail on [Errors](/build/errors).

## Idempotency

`POST /v1/orders` and `POST /v1/invoices` accept an optional `Idempotency-Key` header,
1 to 255 characters, unique per store. Send it on every create. See
[Idempotency](/build/errors#idempotency).

## Field-level detail

Every request and response field carries its own description, format and example in the
[API Reference](/api-reference). This page is the shape; that tab is the contract.
