# Klaim claim API

Klaim hosts Bitcoin gift campaigns on the Lightning Network. Each *claim
code* can be redeemed exactly once for a fixed amount of Bitcoin, sent to
any Lightning destination the holder of the code chooses.

This document describes the HTTP API for autonomous agents. If you are an
agent ("OpenClaw" or otherwise), read this end-to-end before issuing
requests.

## Endpoint

```
POST https://klaim.cash/api/claim
Content-Type: application/json
```

No authentication header is required. The claim code itself is the bearer
secret — anyone holding a valid code can redeem it.

## Request

```json
{
  "code":    "ABC12345",
  "address": "you@walletofsatoshi.com"
}
```

| field     | type   | required | notes                                  |
| --------- | ------ | -------- | -------------------------------------- |
| `code`    | string | yes      | claim code, case-insensitive           |
| `address` | string | yes      | destination — see "Address formats"    |

### Address formats

`address` may be any of the following. Klaim auto-detects the format from
the first few characters; you do not need to declare which kind it is.

#### Recommended default: amountless BOLT11 invoice

Unless the user has expressed a preference for another format, **generate
a fresh amountless BOLT11 invoice** from your own Lightning wallet/node
and pass it as `address`. BOLT11 is the most widely supported, most
reliably routed, and most predictable Lightning payment format — it
gives the cleanest pass/fail signal and avoids ambiguity around offer
discovery, DNS, or LNURL endpoints. An amountless invoice (no amount
encoded in the invoice itself) lets Klaim fill in the gift amount, so
you don't need to know the campaign's payout size up front.

#### All supported formats

- **Amountless BOLT11 invoice** — starts with `lnbc...`. Must be
  amountless. **Use this by default.**
- **BOLT12 offer** — starts with `lno1...`. Use only if the user
  explicitly wants a reusable offer.
- **Lightning Address** — `name@domain.tld`. Use if the user has one
  and prefers it over generating an invoice.
- **Human Bitcoin Address (BIP-353)** — `₿name@domain.tld`. Use if the
  user explicitly asks for HBA. Email-shaped values without the `₿`
  prefix are treated as a Lightning Address.
- **LNURL** — `lnurl1...` or `lnurlp://domain.com/path`. Use if the
  user supplies one.
- **On-chain Bitcoin address** — `bc1...`, `1...`, or `3...`. Use only
  if the user explicitly asks to be paid on-chain.
- **BIP-321 URI** — `bitcoin:bc1...?lightning=lnbc1...`. Useful when
  the user has a single string that bundles both rails.

## Successful response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "ok": true,
  "amount_sats": 1000,
  "destination": "you@walletofsatoshi.com",
  "destination_kind": "lnaddr"
}
```

`destination_kind` reports which payment method actually delivered
the funds. It is one of `bolt11`, `bolt12`, `lnaddr`, `hba`, `lnurl`,
`onchain`, `spontaneous`, or `unknown`. For email-shaped addresses
where both BIP-353 and LNURL records exist on the receiver's domain,
this reflects the rail Klaim actually used (BIP-353 → `hba`,
LNURL → `lnaddr`).

## Error responses

All errors share the shape `{"ok": false, "error": "..."}` with an
appropriate HTTP status. Some errors include an extra `detail` field with
upstream context.

| status | meaning                                                            | retry? |
| ------ | ------------------------------------------------------------------ | ------ |
| `400`  | malformed request — bad JSON, missing field, oversize `address`    | fix and retry |
| `404`  | claim code does not exist or campaign was removed                  | no     |
| `409`  | claim code already used, or another claim is in flight right now   | no     |
| `422`  | claim code is valid but the address could not be paid (unrecognized format, pre-flight rejected by the wallet, or the payment failed terminally) | yes — retry with a different `address` |
| `500`  | payment status is uncertain; the claim is parked for operator review| **no — DO NOT retry** |
| `503`  | the campaign's wallet is temporarily unreachable                   | yes — wait a few seconds |

Klaim does not pre-validate the `address` format itself — the wallet
is the authoritative parser. A single `pay()` attempt is made per
request; there is no in-app fallback between formats. If you want to
try a different format after a `422`, issue a new request with the
new `address`.

A `422` leaves the claim code redeemable. A `500` deliberately does not —
the gift may already be in flight, and reissuing the call could cause a
double payout. Klaim does not currently send an automatic alert on `500`;
the operator finds stuck claims by reviewing the campaign in the admin
UI, so do not assume anyone has been actively notified.

## Examples

In the examples below, `lnbc1p...your-amountless-invoice...` is a
placeholder for a real, freshly-generated, amountless BOLT11 invoice
(typically ~250–400 characters, starts with `lnbc1`). Replace it with
the invoice your wallet/node produced for this claim.

### curl

```bash
curl -X POST https://klaim.cash/api/claim \
  -H 'content-type: application/json' \
  -d '{"code":"ABC12345","address":"lnbc1p...your-amountless-invoice..."}'
```

### Python

```python
import httpx

invoice = my_wallet.create_invoice(memo="klaim gift")  # amountless
resp = httpx.post(
    "https://klaim.cash/api/claim",
    json={"code": "ABC12345", "address": invoice},
    timeout=180,
)
resp.raise_for_status()
print(resp.json())
```

### TypeScript / fetch

```ts
const invoice = await myWallet.createInvoice({ memo: "klaim gift" }); // amountless
const r = await fetch("https://klaim.cash/api/claim", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    code: "ABC12345",
    address: invoice,
  }),
});
const body = await r.json();
console.log(body);
```

## Notes for agents

- **Default to amountless BOLT11.** Generate a fresh invoice from your
  own Lightning wallet/node every time and pass it as `address`. Only
  fall back to other formats (BOLT12, Lightning Address, HBA) when the
  user explicitly asks for one.
- **Don't reuse invoices across calls.** Each BOLT11 invoice is
  single-use and has an expiry; create a new one per claim attempt.
- **Use a generous timeout.** Lightning payments — especially BOLT12
  offers — can spend 30–60 seconds probing routes. Set your client
  timeout to at least 180 seconds.
- **Each code is single-use.** After a `200 OK` the code transitions to
  `claimed` and any further request returns `409`.
- **Treat claim codes as secrets.** They are bearer tokens; store them
  and transmit them like API keys.
- **This API is on Bitcoin MAINNET.** Real funds move. Test against a
  tiny gift first.
