# API quickstart

The send21 API has two building blocks. A **payment request** asks to get paid: the payer opens a link, picks a currency and pays from any wallet. A **payment draft** prepares a payment to someone else, which the sender signs in their own wallet. Base URL: `https://send21.io/api/v1`.

## 1. Create an API key

Sign in and open [API keys](https://send21.io/api-keys). Pick only the scopes you need. Keys look like `s21_...` and are shown once. No key can move funds, because send21 never holds any.

| Scope | Allows |
| --- | --- |
| `drafts:read` | Read drafts, payment requests, templates, status and rates |
| `drafts:write` | Create, cancel and re-quote drafts and payment requests |
| `addressbook:read` | Read saved addresses |
| `addressbook:write` | Change saved addresses |
| `webhooks:manage` | Register and delete webhook endpoints |

## 2. Ask to get paid: a payment request

Price it in any of 165 fiat currencies and list the currencies you accept, each with your own receiving address. The response contains `payPath`; share `https://send21.io` plus that path as a link or QR code. The rate locks when the payer picks a currency.

```bash
curl -X POST https://send21.io/api/v1/payment-requests \
  -H "Authorization: Bearer s21_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{
    "fiatCurrency": "EUR",
    "fiatAmount": 49.00,
    "orderId": "ORDER-1042",
    "memo": "Invoice 1042",
    "options": [
      { "currency": "Eurc", "network": "Base", "address": "0xYourAddress" },
      { "currency": "Usdc", "network": "Solana", "address": "YourSolanaAddress" },
      { "currency": "Btc", "network": "Mainnet", "address": "you@your-wallet.com", "method": "Lightning" }
    ]
  }'
```

## 3. Prepare a payment: a draft

A draft pays a receiver. With `singleOutput: true` it is one QR payment from any wallet, and the send21 fee is billed to your account. Without it, the fee is a separate output and the template suits PSBT and batching wallets. Fetch wallet-ready instructions from `GET /drafts/{id}/tx-template`.

```bash
curl -X POST https://send21.io/api/v1/drafts \
  -H "Authorization: Bearer s21_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payout-77" \
  -d '{
    "receiverAddress": "0xReceiverAddress",
    "network": "Arbitrum",
    "currency": "Usdc",
    "paymentMethod": "MultiOutput",
    "singleOutput": true,
    "fiatCurrency": "SEK",
    "fiatAmount": 1500
  }'
```

## 4. Track the payment

- Poll `GET /drafts/{id}/status` for `AwaitingPayment`, `Seen`, `Confirmed`, `Expired` or `Cancelled`.
- Better: register a [webhook](https://send21.io/docs/webhooks) and react to `draft.confirmed`.
- A transfer within 10% of the billed amount is flagged as `draft.amount_mismatch` and can be accepted with `POST /drafts/{id}/accept-received`.

## Good to know

- Send an `Idempotency-Key` header on create calls. A retry with the same key returns the original object.
- Batch creation: `POST /drafts/batch` takes up to 25 drafts.
- Rate limit: 300 requests per minute per key. A 429 means back off; prefer webhooks over tight polling.
- A 402 on a create call means accrued fees must be settled first; the body names `POST /fees/accrued/settle`.
- Full reference: [/swagger](https://send21.io/swagger) and [/openapi.json](https://send21.io/openapi.json).

---
Source: https://send21.io/docs/quickstart
