Endpoints
Platform keys and health
The public keys that sign price challenges and receipts, the platform fee, and the health check. The health check and the fee need no API key; the public keys need any valid one.
/healthNo auth. { status, time }. It says whether the gateway is up, nothing more. The current challenge-signing key id is signingKeyId on GET /v1/platform/public-key below.
/v1/feesNo auth. The seller fees: { takeRateBps, payoutFeeMicros, current: { takeRateBps, payoutFeeMicros, effectiveFrom, announcedAt }, upcoming: [ … ], noticeDays }. takeRateBps is the platform fee in force, in basis points (500 = 5%), taken from the seller's price. payoutFeeMicros is the flat fee per payout, in micro-dollars ("250000" = $0.25), taken from the amount paid out. upcoming lists announced changes, soonest first; each row carries both fees. An increase in either is always at least noticeDays (30) out; a decrease can take effect at once. A call pays the platform fee in force when it was paid for, a payout the payout fee in force when it was requested.
/v1/platform/public-keyAny valid API key. The ed25519 public key that signs 402 challenges: { publicKeyPem, signingKeyId }. signingKeyId identifies the key, it isn't a credential, and it changes only when the key is rotated. Clients check every challenge against it before signing a payment. The SDKs cache it.
/v1/platform/receipt-keys/:keyIdNo API key needed. The public key for a receipt signing key: { keyId, publicKeyPem }. It's public so anyone holding a receipt can check it, including an x402 buyer with no Zanora account. Old keys stay available after rotation, so an old receipt can always be checked. Returns 404 for an unknown key id.
Verifying a signature yourself
Challenges, payment proofs and receipts are signed the same way:
- Take the object and remove
signatureandsigningKeyId. - Serialise it as canonical JSON: keys sorted at every level, no extra whitespace, amounts as strings.
- Verify the base64
signaturewith ed25519 against the public key.
verifyPayload(body, signature, publicKeyPem) in @zanora/core does this.