{"openapi":"3.1.0","info":{"title":"Voidly Pay","version":"1.21.0","description":"Off-chain agent credit ledger. Sign Ed25519 envelopes, settle transfers, run x402 paywalls, open escrows, stream per-token billing, charge subscriptions, file disputes, post stakes, delegate keys. Stage 2 will swap the backing to USDC on Base without protocol changes.","contact":{"name":"Voidly","url":"https://voidly.ai/pay"},"license":{"name":"MIT"}},"servers":[{"url":"https://api.voidly.ai","description":"Voidly Pay API"}],"components":{"securitySchemes":{"IdempotencyKey":{"type":"apiKey","in":"header","name":"Idempotency-Key","description":"Client-chosen opaque value (≤128 chars). Same key + same body returns cached response. Same key + different body returns 422."}},"schemas":{"DID":{"type":"string","pattern":"^did:voidly:[A-Za-z0-9._-]+$"},"AmountMicro":{"type":"integer","minimum":1,"maximum":1000000000000000,"description":"Amount in micro-credits (1 credit = 1,000,000 micro)."},"ISO8601":{"type":"string","format":"date-time"},"Error":{"type":"object","properties":{"schema":{"type":"string","const":"voidly-pay-error/v1"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string","nullable":true}},"required":["code","message"]}},"required":["schema","error"]},"SignedEnvelope":{"type":"object","description":"All state-changing pay routes accept this shape.","properties":{"envelope":{"type":"object","description":"The schema-tagged envelope. See protocol docs for fields per schema."},"signature":{"type":"string","description":"Ed25519 signature (base64) over canonical JSON of envelope."}},"required":["envelope","signature"]},"TransferReceipt":{"type":"object","properties":{"schema":{"type":"string","const":"voidly-pay-receipt/v1"},"status":{"type":"string","enum":["settled","failed"]},"transfer_id":{"type":"string"},"envelope_hash":{"type":"string"},"settled_at":{"$ref":"#/components/schemas/ISO8601"},"sender_new_balance_micro":{"type":"integer"},"recipient_new_balance_micro":{"type":"integer"},"reason":{"type":"string","nullable":true,"description":"Failure reason code (only when status='failed')."}},"required":["schema","status","transfer_id"]},"Wallet":{"type":"object","properties":{"schema":{"type":"string","const":"voidly-pay-wallet/v1"},"wallet":{"type":"object","properties":{"did":{"$ref":"#/components/schemas/DID"},"balance_credits":{"type":"integer","description":"Current balance in MICRO-credits despite the column name."},"locked_credits":{"type":"integer"},"daily_cap_credits":{"type":"integer"},"per_tx_cap_credits":{"type":"integer"},"frozen":{"type":"integer","enum":[0,1]}},"required":["did","balance_credits","locked_credits"]}},"required":["schema","wallet"]},"PaymentRequired":{"type":"object","properties":{"schema":{"type":"string","const":"voidly-pay-402/v1"},"x402":{"type":"object","properties":{"version":{"type":"integer","const":1},"accepts":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string","description":"e.g. 'voidly-credit'"},"facilitator":{"type":"string","format":"uri"},"resource":{"type":"string"},"method":{"type":"string","nullable":true},"amount_micro":{"type":"integer"},"currency":{"type":"string"},"recipient_did":{"$ref":"#/components/schemas/DID"},"quote_id":{"type":"string"},"expires_at":{"$ref":"#/components/schemas/ISO8601"},"description":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":true},"facilitator_signature":{"type":"string","nullable":true,"description":"Ed25519 base64; verify with x402.facilitator_pubkey."}},"required":["scheme","amount_micro","recipient_did","quote_id","expires_at"]}},"facilitator_pubkey":{"type":"string","nullable":true}}}}}},"responses":{"Error400":{"description":"Invalid envelope or signature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error402":{"description":"Payment required (insufficient balance, missing X-Payment, etc.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error403":{"description":"Forbidden (frozen wallet, recipient not allowlisted, actor not party, etc.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error409":{"description":"Conflict (nonce reuse, idempotency mismatch, state transition not allowed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error429":{"description":"Rate limited or daily cap exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error503":{"description":"System frozen (kill-switch active).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/pay/manifest.json":{"get":{"summary":"Discovery manifest","description":"Lists every endpoint, defaults, MCP tools, and reliability commitment.","responses":{"200":{"description":"OK"}}}},"/v1/pay/health":{"get":{"summary":"Service health","description":"system_frozen flag, wallet count, 24h transfer count.","responses":{"200":{"description":"OK"}}}},"/v1/pay/wallet":{"post":{"summary":"Ensure wallet","description":"Idempotent. Creates a wallet for the given DID if it doesn't exist.","security":[{"IdempotencyKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"did":{"$ref":"#/components/schemas/DID"}},"required":["did"]}}}},"responses":{"200":{"description":"Wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"400":{"$ref":"#/components/responses/Error400"}}}},"/v1/pay/wallet/{did}":{"get":{"summary":"Read wallet","parameters":[{"name":"did","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DID"}}],"responses":{"200":{"description":"Wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"404":{"$ref":"#/components/responses/Error404"}}}},"/v1/pay/transfer":{"post":{"summary":"Submit signed transfer","description":"9-check rule. Atomic settlement.","security":[{"IdempotencyKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Settled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferReceipt"}}}},"400":{"$ref":"#/components/responses/Error400"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"409":{"$ref":"#/components/responses/Error409"},"429":{"$ref":"#/components/responses/Error429"},"503":{"$ref":"#/components/responses/Error503"}}}},"/v1/pay/transfer/{id}":{"get":{"summary":"Read transfer","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9-]{36}$"}}],"responses":{"200":{"description":"Transfer ledger row"},"404":{"$ref":"#/components/responses/Error404"}}}},"/v1/pay/batch":{"post":{"summary":"Atomic multi-recipient transfer","description":"≤100 items, all-or-nothing settlement.","security":[{"IdempotencyKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Batch settled"},"400":{"$ref":"#/components/responses/Error400"},"402":{"$ref":"#/components/responses/Error402"}}}},"/v1/pay/refund":{"post":{"summary":"Refund a settled transfer","description":"Original recipient signs. Partial refunds allowed; sum capped at original amount.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Refunded"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"409":{"$ref":"#/components/responses/Error409"}}}},"/v1/pay/escrow/open":{"post":{"summary":"Open escrow","description":"Locks credits from sender until release/refund/expire.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Escrow opened"}}}},"/v1/pay/escrow/release":{"post":{"summary":"Release escrow","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Released"}}}},"/v1/pay/escrow/refund":{"post":{"summary":"Refund escrow","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Refunded"}}}},"/v1/pay/x402/quote":{"post":{"summary":"Server: create x402 quote","description":"Returns payment_required_response that the server should serve verbatim with HTTP 402.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Quote created","content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string"},"payment_required_response":{"$ref":"#/components/schemas/PaymentRequired"}}}}}}}}},"/v1/pay/proxy":{"get":{"summary":"Universal x402 reverse proxy — paywall any HTTPS URL","description":"Wrap any public HTTPS URL with one query parameter and start charging USDC-backed credits per call. First call returns HTTP 402 with a facilitator-signed quote. Pay it (transfer to recipient DID), retry with X-Payment header → upstream response is fetched + returned. No SDK install required by the URL owner.","parameters":[{"name":"u","in":"query","required":true,"description":"The public HTTPS URL to paywall (URL-encoded).","schema":{"type":"string","format":"uri"}},{"name":"to","in":"query","required":true,"description":"Recipient DID — credits land here on settlement. Must be registered on the rail.","schema":{"$ref":"#/components/schemas/DID"}},{"name":"price","in":"query","required":false,"description":"Price per call in USDC. Range 0.005 – 5.00. Defaults to 0.01.","schema":{"type":"number","minimum":0.005,"maximum":5,"default":0.01}},{"name":"X-Payment","in":"header","required":false,"description":"On retry: 'voidly-credit transfer_id=<id>; quote_id=<id>'.","schema":{"type":"string"}}],"responses":{"200":{"description":"Paid — upstream response streamed back. Includes x-voidly-paid:1, x-voidly-transfer-id, x-voidly-receipt headers.","headers":{"x-voidly-paid":{"schema":{"type":"string","enum":["1"]}},"x-voidly-transfer-id":{"schema":{"type":"string"}},"x-voidly-quote-id":{"schema":{"type":"string"}},"x-voidly-receipt":{"schema":{"type":"string","format":"uri"}},"x-voidly-proxy-upstream":{"schema":{"type":"string","format":"uri"}},"x-voidly-truncated":{"schema":{"type":"string","enum":["1"]},"description":"Set if upstream body was capped at 2 MB."}}},"400":{"description":"Missing / invalid query params (url, recipient, price)."},"402":{"description":"First call (or invalid X-Payment): facilitator-signed x402 quote. Includes www-authenticate: x402, x-voidly-x402:1, x-voidly-quote-id headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"404":{"description":"Recipient DID has no Pay wallet."},"413":{"description":"Upstream body exceeds 2 MB."},"502":{"description":"Upstream unreachable."}}}},"/v1/pay/x402/verify":{"post":{"summary":"Server: verify + consume x402 payment","description":"Pass the X-Payment header value the caller sent. UNIQUE replay protection.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Verified"},"402":{"$ref":"#/components/responses/Error402"}}}},"/v1/pay/x402/facilitator-key":{"get":{"summary":"Facilitator pubkey","description":"Public key clients use to verify facilitator_signature on quotes.","responses":{"200":{"description":"OK"}}}},"/v1/pay/stream/open":{"post":{"summary":"Open metered stream","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Stream opened"}}}},"/v1/pay/stream/meter":{"post":{"summary":"Provider appends meter entry","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Meter appended"}}}},"/v1/pay/stream/finalize":{"post":{"summary":"Requester finalizes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Finalized"}}}},"/v1/pay/subscription/create":{"post":{"summary":"Create recurring subscription","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Subscription created"}}}},"/v1/pay/subscription/{id}/charge":{"post":{"summary":"Charge next due period","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Charged or not_due"}}}},"/v1/pay/dispute/open":{"post":{"summary":"Open dispute (party)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Opened"}}}},"/v1/pay/dispute/resolve":{"post":{"summary":"Resolve dispute (admin)","responses":{"200":{"description":"Resolved"}}}},"/v1/pay/stake/post":{"post":{"summary":"Post stake","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Stake posted"}}}},"/v1/pay/stake/{did}":{"get":{"summary":"Read stake","parameters":[{"name":"did","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DID"}}],"responses":{"200":{"description":"Stake"}}}},"/v1/pay/delegate/authorize":{"post":{"summary":"Authorize delegate (master signs)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Delegate authorized"}}}},"/v1/pay/delegate/revoke":{"post":{"summary":"Revoke delegate (master signs)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Delegate revoked"}}}},"/v1/pay/delegate/{master_did}":{"get":{"summary":"List delegates for master","parameters":[{"name":"master_did","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DID"}}],"responses":{"200":{"description":"Delegate list"}}}},"/v1/pay/webhooks":{"post":{"summary":"Subscribe to events (HMAC-signed delivery)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedEnvelope"}}}},"responses":{"200":{"description":"Subscribed; secret returned ONCE"}}}},"/v1/pay/activity":{"get":{"summary":"Recent activity feed","responses":{"200":{"description":"OK"}}}},"/v1/pay/leaderboard":{"get":{"summary":"Top earners / spenders","responses":{"200":{"description":"OK"}}}},"/v1/pay/feed":{"get":{"summary":"Incremental indexer feed","responses":{"200":{"description":"OK"}}}},"/v1/pay/stats":{"get":{"summary":"Platform aggregates","responses":{"200":{"description":"OK"}}}},"/v1/pay/trust/{did}":{"get":{"summary":"Trust stats","parameters":[{"name":"did","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DID"}}],"responses":{"200":{"description":"OK"}}}},"/v1/pay/rate-limits/{did}":{"get":{"summary":"Per-DID rate limit status","parameters":[{"name":"did","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DID"}}],"responses":{"200":{"description":"OK"}}}}}}