Build
Going live
The switch to live keys, the operational duties, and the failure modes to design for.
Live mode moves real money on a chain with real reorgs. This page is the checklist.
Before you switch keys #
- Verify your payout address. bech32m,
anim1prefix, 34-byte payload, ML-DSA-65 (0x1003). A0x1002SPHINCS+ address is rejected — those addresses exist on this chain but cannot spend, so accepting one would send your revenue somewhere unusable. Prove you control it by receiving a small test payment before you rely on it. - Pick a confirmation depth. Default 12. Lower is faster and riskier. For instantly-delivered digital goods, consider higher.
- Register a production webhook endpoint over https and store its secret where your app secrets live — not in your repository.
- Decide your settlement mode with The splitting limitation open in front of you: merchant-direct plus a signed sweep (non-custodial, default) or forwarding (hands-off, custodial for seconds).
- Rotate anything that leaked. If a secret key has ever been in a browser bundle, a mobile binary, a screenshot, a support ticket or a public repository, rotate it now. Rotation revokes the old key immediately with no grace window, because a grace window is exactly the window an exfiltrated key needs.
Operational duties that do not go away #
| Duty | Why |
|---|---|
| Sweep the protocol fee | In merchant-direct mode you receive the gross and owe 2%. protocol_fee_owed is exact. |
| Reconcile regularly | Compare your orders against settled intents. The reconciler flags anything booked without on-chain support. |
| Watch reorged payments | A PAID intent can return to AWAITING_PAYMENT. Have a human path for that. |
| Keep the webhook endpoint alive | Five consecutive failed deliveries disables it, and re-enabling is manual. |
Handle UNDERPAID and OVERPAID | They never auto-settle. Someone has to decide. |
Failure modes to design for #
- USD pricing becomes unavailable. If no fresh market rate exists, USD checkout fails rather than pricing from a stale number. Your checkout should degrade to an ANM-priced flow or show an honest error — never a guessed price.
- The customer pays after expiry. The money is real and the intent can still move to
PAYMENT_DETECTED. Decide whether that fulfils the order or triggers a refund. - The customer pays twice. One transaction satisfies at most one intent, so the second payment is unattributed money to be refunded, not a double fulfilment.
- Your handler is down during an outage. Retries span roughly 97 seconds, not days. Reconcile against the API after an outage rather than assuming every event arrived.
Do not do these #
- Do not fulfil on
payment.detectedor on mempool visibility. Inclusion is not execution. - Do not trust a client-submitted amount, currency or address. The server decides prices; a client value is input to validate.
- Do not put a secret key in browser or mobile code.
- Do not skip signature verification "temporarily".
- Do not identify payments by amount. Use the reference.