Resolver API reference
The resolver is a compact HTTP boundary for offer discovery, readiness, invoice creation, resolution records, receipts, reconciliation, and webhook operations.
Authentication
Public reads and payment-critical requests remain open: offer fetches, Fiber Address lookup, QR codes, readiness, invoice resolution, receipts, reconciliation, and diagnostics. When RESOLVER_API_KEY is configured, offer inventory, webhook configuration and history, registration, and operator writes require a bearer token, x-api-key, or a signed operator session established through POST /operator/session.
Authorization: Bearer change-me
# or
x-api-key: change-me
Endpoint map
| Method and path | Purpose | Auth when configured |
|---|---|---|
GET /health | Resolver mode and authentication state. | No |
GET|POST|DELETE /operator/session | Inspect, establish, or clear the browser operator session. | POST validates the API key |
GET /diagnostics, GET /topology | Resolver, Fiber RPC, worker, and topology health. | No |
GET /offers | List compact offer summaries for an operator console. | Yes |
POST /offers, POST /demo/offers | Register a signed offer or create a local demo offer. | Yes |
GET /offers/:offer_id | Offer, encoded payload, links, QR URLs, and metadata. | No |
POST /offers/:offer_id/check | Validate a payment request without creating an invoice. | No |
POST /offers/:offer_id/invoice | Create or replay an invoice resolution. | No |
GET /offers/:offer_id/resolutions | List resolution records. | No |
GET|POST /offers/:offer_id/webhooks | List or register webhook endpoints. | Yes |
PATCH|DELETE /offers/:offer_id/webhooks/:webhook_id | Pause, resume, update, or remove an endpoint. | Yes |
POST /offers/:offer_id/webhooks/:webhook_id/test | Send a signed test event to one endpoint. | Yes |
POST /offers/:offer_id/webhooks/:webhook_id/rotate-secret | Rotate and reveal a replacement signing secret once. | Yes |
GET /offers/:offer_id/webhook-events | Inspect event and delivery attempt history. | Yes |
GET /.well-known/fiberoffer/:username | Resolve a Fiber Address. | No |
Create or register an offer
The demo endpoint generates a key pair and signed offer for local development. Production merchants create and sign the offer using the protocol package, then send the encoded offer to POST /offers.
curl -X POST http://localhost:8787/demo/offers \
-H 'content-type: application/json' \
-H 'Authorization: Bearer change-me' \
-d '{
"username": "coffee",
"description": "Coffee checkout",
"pricing_type": "fixed",
"amount": "1000",
"assets": [{ "asset_type": "ckb", "symbol": "CKB" }]
}'
curl -X POST https://resolver.example/offers \
-H 'content-type: application/json' \
-H 'Authorization: Bearer change-me' \
-d '{
"username": "coffee",
"encoded_offer": "fbroffer1..."
}'
The registered response contains offer_id, payment_link, encoded_offer, qr_link_url, qr_offer_url, and the optional fiber_address.
Readiness before invoice creation
Call check whenever the user has selected an amount and asset. It validates signature, pricing rules, assets, single-use state, and merchant invoice availability. Payer route payability remains unknown until the payer wallet dry-runs the fresh invoice using its own node.
POST /offers/:offer_id/check
{
"amount": "1200",
"asset": { "asset_type": "ckb", "symbol": "CKB" }
}
{
"ready": true,
"confidence": "medium",
"next_action": "request_invoice",
"summary": "Request is valid; a fresh Fiber invoice can be created.",
"checks": [],
"blockers": [],
"warnings": []
}
payable is omitted when the payer route is unknown. After invoice creation, the payer wallet calls FiberPaymentClient.checkPaymentRoute(); a successful dry-run returns payable: true and high confidence. A controlled pair fixture may perform this check through the resolver, but it is not required for merchant operation.
Invoice resolution and idempotency
Invoice creation is intentionally separate from readiness. The resolver creates a fresh invoice only after it accepts the request.
POST /offers/:offer_id/invoice
Idempotency-Key: checkout-order-42
content-type: application/json
{
"amount": "1200",
"asset": { "asset_type": "ckb", "symbol": "CKB" }
}
The first successful request returns 201. Retrying exactly the same request and idempotency key returns 200 with idempotent_replay: true. Reusing the key with a different amount or asset returns 409 IDEMPOTENCY_KEY_REUSED.
Scenario: mobile retry after a network timeout
The wallet sends an invoice request but loses the response. It retries with the same idempotency key. The resolver returns the original resolution and invoice, so the user never receives a second invoice for the same checkout attempt.
Records, receipts, and exports
GET /offers/:offer_id/resolutions
GET /offers/:offer_id/resolutions/:resolution_id
POST /offers/:offer_id/resolutions/:resolution_id/status
POST /offers/:offer_id/resolutions/:resolution_id/sync
POST /offers/:offer_id/resolutions/sync
GET /offers/:offer_id/resolutions/:resolution_id/receipt.json
GET /offers/:offer_id/reconciliation.json
GET /offers/:offer_id/reconciliation.csv
Status writes and sync operations are protected when an API key is configured. Receipts and reconciliation files are read-only views intended for merchant systems, support workflows, and accounting exports.