AlgoVoi Gateway — MPP Grade D
On-chain Activity
Compliance Checks
80 issues
- OpenAPI doc exceeds 64KB limit (152766 bytes)
- Missing 402 response declaration on GET /health
- Missing 402 response declaration on POST /v1/verify
- Missing 402 response declaration on POST /v1/ap2/verify
- Missing 402 response declaration on POST /v1/payouts
- Missing 402 response declaration on POST /mpp/challenge
- Missing 402 response declaration on POST /ap2/intent
- Missing 402 response declaration on POST /ap2/cart
- Missing 402 response declaration on POST /ap2/pay
- Missing 402 response declaration on POST /ap2/confirm
- Missing 402 response declaration on GET /ap2/status/{cart_id}
- Missing 402 response declaration on GET /ap2/extensions
- Missing 402 response declaration on GET /extendedAgentCard
- Missing 402 response declaration on POST /message:send
- Missing 402 response declaration on GET /tasks/{task_id}
- Missing 402 response declaration on POST /tasks/{task_id}:cancel
- Missing 402 response declaration on GET /tasks
- Missing 402 response declaration on POST /v1/payment-links
- Missing 402 response declaration on GET /v1/customers
- Missing 402 response declaration on POST /v1/customers
- Missing 402 response declaration on GET /v1/subscriptions
- Missing 402 response declaration on POST /v1/subscriptions
- Missing 402 response declaration on GET /v1/subscriptions/{subscription_id}
- Missing 402 response declaration on PATCH /v1/subscriptions/{subscription_id}
- Missing 402 response declaration on POST /v1/subscriptions/{subscription_id}/cancel
- Missing 402 response declaration on POST /v1/subscriptions/{subscription_id}/pause
- Missing 402 response declaration on POST /v1/subscriptions/{subscription_id}/resume
- Missing 402 response declaration on GET /v1/subscriptions/{subscription_id}/invoices
- Missing 402 response declaration on GET /subscription/{cancel_secret}/cancel
- Missing 402 response declaration on POST /subscription/{cancel_secret}/cancel
- Missing 402 response declaration on POST /v1/recurr/auth/challenge
- Missing 402 response declaration on POST /v1/recurr/auth/verify
- Missing 402 response declaration on GET /v1/recurr/me/subscriptions
- Missing 402 response declaration on GET /v1/recurr/me/subscriptions/{subscription_id}
- Missing 402 response declaration on POST /v1/recurr/me/subscriptions/{subscription_id}/cancel
- Missing 402 response declaration on GET /v1/recurr/me/invoices
- Missing 402 response declaration on GET /recurr/portal
- Missing 402 response declaration on GET /recurr/cancel/{cancel_secret}
- Missing 402 response declaration on POST /recurr/cancel/{cancel_secret}
- Missing 402 response declaration on GET /v1/recurring/authorities
- Missing 402 response declaration on POST /v1/recurring/authorities
- Missing 402 response declaration on GET /v1/recurring/authorities/{authority_id}
- Missing 402 response declaration on POST /v1/recurring/authorities/{authority_id}/confirm
- Missing 402 response declaration on POST /v1/recurring/authorities/{authority_id}/revoke
- Missing 402 response declaration on POST /v1/recurring/authorities/{authority_id}/pause
- Missing 402 response declaration on POST /v1/recurring/authorities/{authority_id}/resume
- Missing 402 response declaration on POST /v1/recurring/pulls
- Missing 402 response declaration on GET /v1/recurring/auth/{token}
- Missing 402 response declaration on POST /v1/recurring/auth/{token}/confirm
- Missing 402 response declaration on GET /v1/recurring/contracts/algorand/spending_cap_vault_v1
- Missing 402 response declaration on GET /resources/{resource_id}
- Missing 402 response declaration on POST /x402/challenge
- Missing 402 response declaration on POST /x402/verify
- Missing 402 response declaration on POST /checkout/{token}/verify
- Missing 402 response declaration on GET /checkout/{token}/qr
- Missing 402 response declaration on GET /checkout/{token}/build-txn
- Missing 402 response declaration on POST /checkout/{token}/submit-txn
- Missing 402 response declaration on GET /checkout/{token}/detect
- Missing 402 response declaration on POST /checkout/{token}/submit-sponsored
- Missing 402 response declaration on POST /checkout/{token}/abandon
- Missing 402 response declaration on POST /checkout/{token}/cancel
- Missing 402 response declaration on GET /checkout/{token}/xchain/bridge-info
- Missing 402 response declaration on POST /checkout/{token}/xchain/bridge-send
- Missing 402 response declaration on POST /checkout/{token}/xchain/source-tx-recorded
- Missing 402 response declaration on GET /checkout/{token}/xchain/bridge-status/{tx_hash}
- Missing 402 response declaration on POST /checkout/{token}/xchain/prepare
- Missing 402 response declaration on POST /checkout/{token}/xchain/prepare-optin
- Missing 402 response declaration on POST /checkout/{token}/xchain/optin-submit
- Missing 402 response declaration on POST /checkout/{token}/xchain/submit
- Missing 402 response declaration on GET /checkout/{token}/status
- Missing 402 response declaration on GET /compliance/attestation
- Missing 402 response declaration on POST /compliance/screen
- Missing 402 response declaration on GET /discovery/resources
- Missing 402 response declaration on POST /signup/create
- Missing 402 response declaration on POST /cloud-signup/create
- Missing 402 response declaration on POST /mandate/pay
- Missing 402 response declaration on GET /mandate/portal/{mandate_id}
- Missing 402 response declaration on POST /mandate/portal/{mandate_id}/topup/initiate
- Missing 402 response declaration on POST /mandate/portal/{mandate_id}/topup/capture
- Endpoint GET /health returned 200 without payment
Paid Operations (88)
GET /health dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
POST /v1/verify dynamic
Verify an on-chain payment transaction for the MPP adapter. The adapter submits the tx_id and network from the payer's credential; the gateway looks up the resource definition to get the expected amount and receiver, then delegates to the facilitator for on-chain confirmation. Returns a receipt JWT on success.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/MppVerifyRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/MppVerifyResponse"
}
POST /v1/ap2/verify dynamic
Verify an AP2 mandate credential submitted by a payer. The mandate dict must contain a ``signature`` field holding the JWT access token issued by POST /ap2/confirm. The gateway verifies the JWT signature, checks that the tenant_id claim matches the authenticated tenant, and confirms the token has not expired. Returns ``{"verified": true}`` on success.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/Ap2VerifyRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/Ap2VerifyResponse"
}
POST /v1/payouts dynamic
Initiate an on-chain transfer from the tenant's custodial balance. Idempotent on ``reference``: submitting the same reference twice returns the original payout_id + tx_id without re-broadcasting to the chain. Supported networks (MVP): algorand_mainnet, voi_mainnet (USDC / aUSDC). currency must be USD (USDC peg assumed 1:1).
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/PayoutCreate"
}
Response Schema (200)
{
"$ref": "#/components/schemas/PayoutCreateResponse"
}
POST /mpp/challenge dynamic
Explicit challenge pre-fetch for MPP agents that want to obtain a challenge token before building their payment transaction. Returns the same challenge object that GET /mpp/{resource_id} returns in its 401 body, allowing agents to pipeline challenge fetch → pay → proof submission without the round-trip to the resource endpoint.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/MppChallengeRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/MppChallengeResponse"
}
GET /mpp/probe dynamic
Discovery probe + operator-level paid resource. No Authorization header → 402 + WWW-Authenticate: Payment challenge. Authorization: Payment <proof> → verify on-chain → 200 receipt. Payment goes to the AlgoVoi operator address (not a tenant). No DB session needed — facilitator verifies on-chain; receipt is logged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402, mpp
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402 mpp]
Input Schema
{
"additionalProperties": true,
"description": "Optional payment proof or invocation parameters",
"example": {},
"type": "object"
}
POST /mpp/probe dynamic
Discovery probe + operator-level paid resource. No Authorization header → 402 + WWW-Authenticate: Payment challenge. Authorization: Payment <proof> → verify on-chain → 200 receipt. Payment goes to the AlgoVoi operator address (not a tenant). No DB session needed — facilitator verifies on-chain; receipt is logged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402, mpp
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402 mpp]
Input Schema
{
"additionalProperties": true,
"description": "Optional payment proof or invocation parameters",
"example": {},
"type": "object"
}
PUT /mpp/probe dynamic
Discovery probe + operator-level paid resource. No Authorization header → 402 + WWW-Authenticate: Payment challenge. Authorization: Payment <proof> → verify on-chain → 200 receipt. Payment goes to the AlgoVoi operator address (not a tenant). No DB session needed — facilitator verifies on-chain; receipt is logged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402, mpp
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402 mpp]
Input Schema
{
"additionalProperties": true,
"description": "Optional payment proof or invocation parameters",
"example": {},
"type": "object"
}
PATCH /mpp/probe dynamic
Discovery probe + operator-level paid resource. No Authorization header → 402 + WWW-Authenticate: Payment challenge. Authorization: Payment <proof> → verify on-chain → 200 receipt. Payment goes to the AlgoVoi operator address (not a tenant). No DB session needed — facilitator verifies on-chain; receipt is logged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402, mpp
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402 mpp]
Input Schema
{
"additionalProperties": true,
"description": "Optional payment proof or invocation parameters",
"example": {},
"type": "object"
}
DELETE /mpp/probe dynamic
Discovery probe + operator-level paid resource. No Authorization header → 402 + WWW-Authenticate: Payment challenge. Authorization: Payment <proof> → verify on-chain → 200 receipt. Payment goes to the AlgoVoi operator address (not a tenant). No DB session needed — facilitator verifies on-chain; receipt is logged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402, mpp
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402 mpp]
Input Schema
{
"additionalProperties": true,
"description": "Optional payment proof or invocation parameters",
"example": {},
"type": "object"
}
GET /mpp/{resource_id} dynamic
IETF draft-httpauth-payment resource gate. No Authorization header → HTTP 401 + WWW-Authenticate: Payment challenge. Authorization: Payment <b64> → validate challenge echo → verify on-chain → HTTP 200. The x402 /protected/{resource_id} endpoint is completely unchanged.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- mpp, x402
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [mpp x402]
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| resource_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| authorization | header | No | - | |
| x-tenant-id | header | No | - |
GET /mpp/sub/{resource_id} dynamic
MPP subscription gate (API key auth). No proof → 402 + intent="subscription" challenge with periodCount/periodUnit. Credential present → verify authority tx → create MppSubscription → return subscriptionId.
- Amount
- dynamic
- Currency
- -
- Method
- mpp
- Intent
- subscription
- 402 Declared
- Yes
authMode: payment protocols: [mpp]
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| resource_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| authorization | header | No | - | |
| Idempotency-Key | header | No | - | |
| x-tenant-id | header | No | - |
POST /mpp/sub/{resource_id} dynamic
MPP subscription gate (API key auth). No proof → 402 + intent="subscription" challenge with periodCount/periodUnit. Credential present → verify authority tx → create MppSubscription → return subscriptionId.
- Amount
- dynamic
- Currency
- -
- Method
- mpp
- Intent
- subscription
- 402 Declared
- Yes
authMode: payment protocols: [mpp]
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| resource_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| authorization | header | No | - | |
| Idempotency-Key | header | No | - | |
| x-tenant-id | header | No | - |
POST /ap2/intent dynamic
Receive an IntentMandate. If user_authorization is present (SD-JWT-VC), verification is deferred to /pay where it binds to specific cart and payment hashes — at /intent stage we have nothing concrete to bind to. Per spec: if intent is not user-signed, user_cart_confirmation_required MUST be True (otherwise the agent could shop unilaterally without consent).
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AP2IntentRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AP2IntentResponse"
}
POST /ap2/cart dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AP2CartRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AP2CartResponse"
}
POST /ap2/pay dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AP2PayRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AP2PayResponse"
}
POST /ap2/confirm dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AP2ConfirmRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AP2ConfirmResponse"
}
GET /ap2/status/{cart_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cart_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/AP2StatusResponse"
}
GET /ap2/extensions dynamic
Returns the AP2 extensions this gateway supports. Used by AP2 agents to discover available payment methods (e.g. AlgoVoi crypto rails) before constructing a CartMandate.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Response Schema (200)
{
"$ref": "#/components/schemas/AP2ExtensionsResponse"
}
GET /extendedAgentCard dynamic
Authenticated extended agent card. Returns the base card enriched with tenant-specific endpoint info.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
POST /message:send dynamic
Send a message to the AlgoVoi payment agent. The agent processes the task synchronously and returns the completed task within the same response. All three payment skills are supported: verify-payment, create-checkout, check-status. Input DataPart must include a 'skill' field identifying which skill to invoke.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/_SendMessageRequest"
}
GET /tasks/{task_id} dynamic
Get the current state of a task by ID.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| task_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
POST /tasks/{task_id}:cancel dynamic
Cancel a task. Since AlgoVoi tasks complete synchronously, only tasks in 'submitted' or 'working' state can be cancelled. Completed/failed tasks return 409.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| task_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
GET /tasks dynamic
List recent tasks for this session. Returns tasks from the in-process store (TTL 10 minutes). In production, tasks complete within the send_message call so this endpoint is primarily for debugging.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
POST /v1/payment-links dynamic
Create a hosted checkout link for a specific fiat amount. The amount is converted to stablecoin (USDC / aUSDC) or native crypto using the tenant's configured network and the live FX rate. The returned `checkout_url` can be sent directly to the buyer.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/DynamicPaymentLinkCreate"
}
GET /v1/customers dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/CustomerResponse"
},
"title": "Response List Customers Endpoint V1 Customers Get",
"type": "array"
}
POST /v1/customers dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/CustomerCreate"
}
GET /v1/subscriptions dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | No | Filter by status | |
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/SubscriptionResponse"
},
"title": "Response List Subscriptions Endpoint V1 Subscriptions Get",
"type": "array"
}
POST /v1/subscriptions dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/SubscriptionCreate"
}
GET /v1/subscriptions/{subscription_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
PATCH /v1/subscriptions/{subscription_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/SubscriptionUpdate"
}
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
POST /v1/subscriptions/{subscription_id}/cancel dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"anyOf": [
{
"$ref": "#/components/schemas/CancelSubscriptionBody"
},
{
"type": "null"
}
],
"title": "Body"
}
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
POST /v1/subscriptions/{subscription_id}/pause dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
POST /v1/subscriptions/{subscription_id}/resume dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
GET /v1/subscriptions/{subscription_id}/invoices dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/SubscriptionInvoiceResponse"
},
"title": "Response List Subscription Invoices Endpoint V1 Subscriptions Subscription Id Invoices Get",
"type": "array"
}
GET /subscription/{cancel_secret}/cancel dynamic
Public page — single-use cancel link given to customer at signup. GET shows a confirmation page; POST commits the cancellation.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cancel_secret | path | string | Yes | - |
Response Schema (200)
{
"type": "string"
}
POST /subscription/{cancel_secret}/cancel dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cancel_secret | path | string | Yes | - |
Response Schema (200)
{
"type": "string"
}
POST /v1/recurr/auth/challenge dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Input Schema
{
"$ref": "#/components/schemas/shared__schemas__recurr__ChallengeRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/shared__schemas__recurr__ChallengeResponse"
}
POST /v1/recurr/auth/verify dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Input Schema
{
"$ref": "#/components/schemas/shared__schemas__recurr__VerifyRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/shared__schemas__recurr__VerifyResponse"
}
GET /v1/recurr/me/subscriptions dynamic
Cross-tenant. Returns every subscription where the wallet matches a customer row, regardless of which tenant owns that subscription.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | No | - | |
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/SubscriptionResponse"
},
"title": "Response My Subscriptions V1 Recurr Me Subscriptions Get",
"type": "array"
}
GET /v1/recurr/me/subscriptions/{subscription_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
POST /v1/recurr/me/subscriptions/{subscription_id}/cancel dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | path | string | Yes | - |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/SubscriptionResponse"
}
GET /v1/recurr/me/invoices dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | query | No | - | |
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/SubscriptionInvoiceResponse"
},
"title": "Response My Invoices V1 Recurr Me Invoices Get",
"type": "array"
}
GET /recurr/portal dynamic
Tenant-agnostic customer portal — connect wallet, see all subscriptions across every merchant who has billed that wallet. Embeds zero JS framework. Wallets: - EVM (Base, Tempo, ...): MetaMask injected provider + EIP-191 personal_sign - Solana: window.solana (Phantom) - Algorand / VOI: Pera, Defly, Lute (signData with "MX" prefix) - Stellar: Stellar Wallets Kit (Freighter, Albedo, xBull, Lobstr, Hana, Rabet) - Hedera: Hedera Wallet Connect (HashPack, Blade, Kabila) via Reown Security: pre-sale Comet third-pass review (2026-05-07, Task A) caught that the previous `replace('"', "")` sanitisation of the `chain` query parameter was insufficient — single quotes and semicolons fell through into a JS string literal under the legacy 'unsafe-inline' CSP applied to /recurr/portal, enabling reflected XSS via `?chain='; alert(1);//`. Replaced with a strict allowlist. The `wc_pid` reflection is also tightened to a 32-char-hex regex even though it sources from settings.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| chain | query | string | No | Default chain for wallet-connect |
Response Schema (200)
{
"type": "string"
}
GET /recurr/cancel/{cancel_secret} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cancel_secret | path | string | Yes | - |
Response Schema (200)
{
"type": "string"
}
POST /recurr/cancel/{cancel_secret} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cancel_secret | path | string | Yes | - |
Response Schema (200)
{
"type": "string"
}
GET /v1/recurring/authorities dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| subscription_id | query | No | - | |
| status | query | No | Filter by status | |
| limit | query | integer | No | - |
| offset | query | integer | No | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"items": {
"$ref": "#/components/schemas/AuthorityResponse"
},
"title": "Response List Authorities Endpoint V1 Recurring Authorities Get",
"type": "array"
}
POST /v1/recurring/authorities dynamic
Create a Tier 2 standing authority for an existing subscription. Returns the server-recorded authority (status='pending') plus the chain-specific payload the customer's wallet signs to land the on-chain authorisation. The AlgoVoi widget consumes the payload; the customer signs the 6-action atomic group; AlgoVoi confirms the landing and a separate POST /confirm transitions to 'active'.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AuthorityCreate"
}
GET /v1/recurring/authorities/{authority_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authority_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/AuthorityResponse"
}
POST /v1/recurring/authorities/{authority_id}/confirm dynamic
Mark an authority active after on-chain landing. The tenant calls this once they (or the AlgoVoi widget) has confirmed the customer's signed transaction group landed on-chain. ``on_chain_address`` carries the chain-specific identifier (e.g. ``app:<application_id>``).
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authority_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AuthorityConfirmRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AuthorityResponse"
}
POST /v1/recurring/authorities/{authority_id}/revoke dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authority_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/AuthorityResponse"
}
POST /v1/recurring/authorities/{authority_id}/pause dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authority_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/AuthorityResponse"
}
POST /v1/recurring/authorities/{authority_id}/resume dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authority_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/AuthorityResumeRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/AuthorityResponse"
}
POST /v1/recurring/pulls dynamic
Manually request a pull cycle. Returns the (unchanged) authority record. The actual chain-side pull submission is performed by the Sprint 1.5c cycle reaper (which this endpoint signals via setting ``next_cycle_due_at = now``). For 1.5b this endpoint validates the request shape and updates next_cycle_due_at; the reaper picks up on its next sweep. 202 Accepted — the pull will execute on the reaper's next tick, not synchronously.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/PullCreate"
}
GET /v1/recurring/auth/{token} dynamic
Public endpoint consumed by recurr.algovoi.co.uk to render the Authority Summary Card. Returns 410 Gone in constant time for any not-found / expired / consumed token to prevent enumeration.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
Response Schema (200)
{
"$ref": "#/components/schemas/HostedAuthResolveResponse"
}
POST /v1/recurring/auth/{token}/confirm dynamic
Called by recurr.algovoi.co.uk after the customer's wallet has signed and the on-chain transaction has landed. Fires a sanctions screen on the wallet address (pre-activation gate) and writes authority_signed + authority_confirmed audit-chain events. Idempotent: re-confirms with the same on_chain_address return 200 with the existing row; mismatched address returns 409.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
| Idempotency-Key | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/HostedAuthConfirmRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/HostedAuthConfirmResponse"
}
GET /v1/recurring/contracts/algorand/spending_cap_vault_v1 dynamic
Return the compiled approval + clear TEAL programs for the hosted-auth page to construct and sign the vault-deploy ApplicationCreate transaction.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Response Schema (200)
{
"additionalProperties": true,
"title": "Response Get Algorand Spending Cap Vault V1 V1 Recurring Contracts Algorand Spending Cap Vault V1 Get",
"type": "object"
}
GET /protected/{resource_id} dynamic
x402-compliant protected resource endpoint. Accepts payment proof via either header (compatible with both specs): - X-PAYMENT (gateway spec) - PAYMENT-SIGNATURE (coinbase/x402 spec, used by AlgoVoi extension) - No payment header → HTTP 402 + PAYMENT-REQUIRED header - Payment header → verify on-chain → HTTP 200 + body
- Amount
- map[amount:10000 currency:31566704 mode:fixed]
- Currency
- -
- Method
- mpp, x402
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:31566704 mode:fixed] protocols: [mpp x402]
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| resource_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-payment | header | No | - | |
| PAYMENT-SIGNATURE | header | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
GET /resources/{resource_id} dynamic
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| resource_id | path | string | Yes | - |
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/ResourceResponse"
}
POST /x402/challenge dynamic
Return payment instructions using per-resource price/network and per-tenant payout address.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/gateway__app__routers__verify__ChallengeRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/gateway__app__routers__verify__ChallengeResponse"
}
POST /x402/verify dynamic
Submit tx_id for verification using per-tenant payout address as expected receiver.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - | |
| x-tenant-id | header | No | - | |
| authorization | header | No | - |
Input Schema
{
"$ref": "#/components/schemas/gateway__app__routers__verify__VerifyRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/gateway__app__routers__verify__VerifyResponse"
}
POST /checkout/{token}/verify dynamic
Verify the payer's on-chain transaction and mark the payment link paid. The payer must have sent exactly the required amount to the receiver address on the correct chain. The facilitator performs the on-chain verification. Returns the redirect_url on success so the browser JS can redirect. Returns 422 if the transaction is invalid or cannot be verified. Returns 409 if the link is already paid. Returns 410 if the link is expired or cancelled.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
Input Schema
{
"$ref": "#/components/schemas/CheckoutVerifyRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/CheckoutVerifyResponse"
}
GET /checkout/{token}/qr dynamic
Generate a QR code PNG for any short string (used for WalletConnect pairing URIs). Returns image/png so the browser can use it as <img src=...> without any JS QR library.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
| data | query | string | Yes | - |
GET /checkout/{token}/build-txn dynamic
Build an unsigned Algorand/VOI transaction for WalletConnect signing. Caller supplies ?sender=<address>. Returns {unsigned_txn: <base64>} ready to pass straight to algo_signTxn — no algosdk needed in the browser.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
| sender | query | string | Yes | - |
POST /checkout/{token}/submit-txn dynamic
Accept a base64-encoded signed Algorand/VOI transaction, submit it to algod, and return the tx_id for verification via the existing /verify endpoint.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
GET /checkout/{token}/detect dynamic
Auto-detect inbound payment by polling the chain's indexer/mirror node. Supports all chains: - Algorand/VOI: queries indexer /v2/transactions?address=...¬e-prefix=... - Hedera: queries Mirror Node /api/v1/transactions?account.id=... Returns {"found": true, "tx_id": "..."} when detected, or {"found": false}.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/submit-sponsored dynamic
Accept a customer's signed 0-fee transaction and submit it via the tenant's sponsor wallet (atomic group fee pooling). Body: { "signed_tx": base64, "chain": "algorand-mainnet" | "voi-mainnet" } If the tenant has no sponsor wallet configured, returns {"error": "not_sponsored", "fallback": true} so the client can fall back to normal payment flow.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
Input Schema
{
"additionalProperties": true,
"title": "Body",
"type": "object"
}
POST /checkout/{token}/abandon dynamic
Customer-initiated checkout abandonment. No `cancel_secret` required: anyone who has the checkout URL can already walk away from their own checkout. This endpoint just makes the abandonment EXPLICIT to the platform — without it, the merchant order stays in `Pending` indefinitely, and OpenCart's `algovoi.callback` polling our `/status` would still see `active`, leading to confusing UX where a cancelled checkout returns to the merchant's checkout page instead of the merchant's "order cancelled" page. Only `active` links can be abandoned: * `paid` → 409 Conflict (let the JS show "Payment confirmed" instead) * `cancelled`→ 200 (idempotent — already cancelled) * `expired` → 410 Gone On success: marks `link.status = 'cancelled'` AND notifies the merchant platform (OpenCart etc.) to mark the order as Cancelled on their side. Always returns the redirect_url so the JS can wire the "Return to store" link target.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/cancel dynamic
Cancel an active checkout link. Sets status to 'cancelled'. F5 security fix: requires cancel_secret in the request body. The secret is generated at link-creation time and returned to the merchant only — it is never embedded in the public checkout page. This prevents an attacker who merely knows the checkout URL from cancelling the link. Only active links can be cancelled. Paid/expired/already-cancelled links return 409/410. Returns redirect_url so callers can redirect customers.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
Input Schema
{
"$ref": "#/components/schemas/CancelCheckoutRequest"
}
GET /checkout/{token}/xchain/bridge-info dynamic
Return all EVM chains Allbridge supports as bridge SOURCES for the tenant's configured destination chain (Algorand USDCa or Solana USDC), pre-computed with the exact send amount (checkout amount + bridge fee). Also returns the destination metadata so the frontend can render the right "USDC on <chain>" label without a second round-trip.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/xchain/bridge-send dynamic
Build the swapAndBridge calldata server-side and return it for MetaMask to sign. Body schema: Required: evm_address, chain_id, usdc_address, bridge_amount One of: algo_address (legacy field name, used for Algorand destination) recipient_address (preferred — works for any destination) Returns: { to, data, value } — pass directly to eth_sendTransaction. The destination chain is taken from the tenant's xchain_destination_chain setting; the frontend doesn't pass it (and shouldn't be allowed to, because that would let a hostile shopper redirect bridge inflow to a different chain).
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/xchain/source-tx-recorded dynamic
Called by the frontend immediately after MetaMask returns a tx hash for the swapAndBridge call. Records the source_tx_hash on the bridge-attempt row, advancing its state from `pending_signature` to `pending_bridge`. Body: { attempt_id: int, source_tx_hash: str } Idempotent: re-POSTing with the same source_tx_hash for the same attempt is a no-op. Mismatched source_tx_hash on a row that already has one is rejected with 400 — exactly one source tx per attempt. Per Comet review 2026-05-04 — without this, AlgoVoi can't reconcile Allbridge's destination tx back to the shopper's checkout.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
GET /checkout/{token}/xchain/bridge-status/{tx_hash} dynamic
Poll Allbridge for cross-chain transfer completion + advance the bridge-attempt lifecycle. Reads `tx_hash` as the SOURCE-chain tx (the one MetaMask returned). Looks up the persisted attempt by source_tx_hash, polls Allbridge, and on completion records the destination tx hash on the attempt row so the verifier can run against the SPECIFIC dest tx (not "any matching tx in window"). Idempotent — repeated polls only update DB state on transitions.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
| tx_hash | path | string | Yes | - |
POST /checkout/{token}/xchain/prepare dynamic
Derive the Algorand LogicSig address for an EVM wallet and check funding. If sufficiently funded, builds the unsigned payment tx ready for EIP-712 signing. Body: { "evm_address": "0x..." }
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/xchain/prepare-optin dynamic
Fund the LogicSig address from the platform sponsor wallet and build an unsigned USDCa opt-in transaction for EIP-712 signing. Body: { "evm_address": "0x..." } Returns: { "eip712_message": {...} }
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/xchain/optin-submit dynamic
Sign and submit the pending USDCa opt-in transaction. Body: { "evm_address": "0x...", "signature": "0x..." } Returns: { "optin_tx_id": "..." }
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
POST /checkout/{token}/xchain/submit dynamic
Sign and submit the pending xChain transaction using the EVM wallet's EIP-712 signature. Body: { "evm_address": "0x...", "signature": "0x..." } Returns { "tx_id": "..." }
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
GET /checkout/{token}/status dynamic
Polling endpoint — returns whether the link has been paid. Safe to call repeatedly; does not mutate state. Returns { "status": "active"|"paid"|"expired"|"cancelled", "redirect_url": str|null }
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | path | string | Yes | - |
GET /compliance/attestation dynamic
Return the gateway's full compliance posture as a verifiable transparency surface. Free, no rate limit (cached server-side).
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
POST /compliance/screen dynamic
Pre-payment recipient screen. Returns a SAMLA-compliant verdict.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Input Schema
{
"$ref": "#/components/schemas/ScreenRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/ScreenResponse"
}
GET /discovery/resources dynamic
Return the Bazaar-shaped list of x402-payable resources on this facilitator. See module docstring for schema + scope. The Agent Trust Bench has its own Bazaar surface at https://agent-trust-bench.algovoi.co.uk/discovery/resources since the bench was extracted to its own service on VM4 (2026-05-09). This gateway's catalog is now scoped to tenant resources only; bench resources are advertised by the bench's own discovery endpoint as the canonical source. A `related_facilitators` hint points Bazaar crawlers at the bench so cross-facilitator discovery still works.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
GET /r/{tenant_short_id}/{resource_id} dynamic
Public, tenant-scoped x402 resource endpoint. See module docstring.
- Amount
- map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed]
- Currency
- -
- Method
- x402
- Intent
- -
- 402 Declared
- Yes
authMode: payment price: map[amount:10000 currency:0x20c000000000000000000000b9537d11c60e8b50 mode:fixed] protocols: [x402]
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_short_id | path | string | Yes | - |
| resource_id | path | string | Yes | - |
| X-PAYMENT | header | No | - | |
| PAYMENT-SIGNATURE | header | No | - |
POST /signup/create dynamic
Proxy wallet signup request to control plane. Rate limited at 5/hour per real client IP (via X-Real-IP / X-Forwarded-For). This limit is the real enforcement point — the control_plane's limiter sees only the gateway container IP so it's a shared bucket.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Input Schema
{
"additionalProperties": true,
"title": "Body",
"type": "object"
}
POST /cloud-signup/create dynamic
Proxy email/cloud signup request to control plane. Rate limited at 5/hour per real client IP — same enforcement as wallet signup.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: none
Input Schema
{
"additionalProperties": true,
"title": "Body",
"type": "object"
}
POST /mandate/pay dynamic
Pay for a resource using a mandate JWT. The mandate JWT is passed as a standard HTTP Bearer token. No X-Tenant-Id header is required — mandate tokens are cross-tenant. On success, the mandate's balance_minor is debited and an on-chain transfer from AlgoVoi's hot wallet to the merchant is executed. The response contains a signed access_token granting access to the resource.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| tenant_id | query | No | - |
Input Schema
{
"$ref": "#/components/schemas/MandatePayRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/MandatePayResponse"
}
GET /mandate/portal/{mandate_id} dynamic
Load public portal view for a mandate. Returns balance, status, JWT token (if active), and last 10 charges. The mandate_id is the user's credential — treat it like an account number.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| mandate_id | path | string | Yes | - |
| include_token | query | boolean | No | Include JWT token in response |
| tenant_id | query | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/MandatePortalResponse"
}
POST /mandate/portal/{mandate_id}/topup/initiate dynamic
Initiate a PayPal top-up for a mandate. Returns an approval_url — redirect the user's browser there. After approval, PayPal redirects to return_url with ?token=<paypal_order_id>. Then call POST /topup/capture with that token.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| mandate_id | path | string | Yes | - |
| tenant_id | query | No | - |
Input Schema
{
"$ref": "#/components/schemas/TopupInitiateRequest"
}
Response Schema (200)
{
"$ref": "#/components/schemas/TopupInitiateResponse"
}
POST /mandate/portal/{mandate_id}/topup/capture dynamic
Capture a PayPal payment after buyer approval. Idempotent — safe to call again if the first attempt timed out.
- Amount
- dynamic
- Currency
- -
- Method
- -
- Intent
- -
authMode: api_key
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| mandate_id | path | string | Yes | - |
| token | query | string | Yes | PayPal order token |
| tenant_id | query | No | - |
Response Schema (200)
{
"$ref": "#/components/schemas/TopupCaptureResponse"
}
Payment Methods
- Methods
- -
- Intents
- subscription
- Currencies (discovery)
- -
- Multiple Challenges
- No
Security
- TLS Version
- TLSv1.3
- Challenge ID Unique
- -
- Challenge ID Length
- -
- Digest Binding
- -
Uptime
- Discovery
- Reachable (129ms)
- Challenge
- Reachable (73ms)
- Last Checked
Schema Completeness
- Paid Operations
- 88
- With Input Schema
- 36
- With Description
- 88
52 missing schema
- GET /health
- GET /mpp/{resource_id}
- GET /mpp/sub/{resource_id}
- POST /mpp/sub/{resource_id}
- GET /ap2/status/{cart_id}
- GET /ap2/extensions
- GET /extendedAgentCard
- GET /tasks/{task_id}
- POST /tasks/{task_id}:cancel
- GET /tasks
- GET /v1/customers
- GET /v1/subscriptions
- GET /v1/subscriptions/{subscription_id}
- POST /v1/subscriptions/{subscription_id}/pause
- POST /v1/subscriptions/{subscription_id}/resume
- GET /v1/subscriptions/{subscription_id}/invoices
- GET /subscription/{cancel_secret}/cancel
- POST /subscription/{cancel_secret}/cancel
- GET /v1/recurr/me/subscriptions
- GET /v1/recurr/me/subscriptions/{subscription_id}
- POST /v1/recurr/me/subscriptions/{subscription_id}/cancel
- GET /v1/recurr/me/invoices
- GET /recurr/portal
- GET /recurr/cancel/{cancel_secret}
- POST /recurr/cancel/{cancel_secret}
- GET /v1/recurring/authorities
- GET /v1/recurring/authorities/{authority_id}
- POST /v1/recurring/authorities/{authority_id}/revoke
- POST /v1/recurring/authorities/{authority_id}/pause
- GET /v1/recurring/auth/{token}
- GET /v1/recurring/contracts/algorand/spending_cap_vault_v1
- GET /protected/{resource_id}
- GET /resources/{resource_id}
- GET /checkout/{token}/qr
- GET /checkout/{token}/build-txn
- POST /checkout/{token}/submit-txn
- GET /checkout/{token}/detect
- POST /checkout/{token}/abandon
- GET /checkout/{token}/xchain/bridge-info
- POST /checkout/{token}/xchain/bridge-send
- POST /checkout/{token}/xchain/source-tx-recorded
- GET /checkout/{token}/xchain/bridge-status/{tx_hash}
- POST /checkout/{token}/xchain/prepare
- POST /checkout/{token}/xchain/prepare-optin
- POST /checkout/{token}/xchain/optin-submit
- POST /checkout/{token}/xchain/submit
- GET /checkout/{token}/status
- GET /compliance/attestation
- GET /discovery/resources
- GET /r/{tenant_short_id}/{resource_id}
- GET /mandate/portal/{mandate_id}
- POST /mandate/portal/{mandate_id}/topup/capture
Documentation
- Homepage
- -
- API Reference
- -
- llms.txt
- -
Discovery
- OpenAPI URL
- https://api.algovoi.co.uk/openapi.json
- OpenAPI Version
- 3.1.0
- Service Version
- 1.0.0-phase1c
- Document Size
- 152766 bytes
- Document Hash
- 68bcfba1a2c133c2275b6b02605e95a4a8047233df140b84cc743e5ffd27d340
Version History (17 snapshots)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- new endpoint: GET /v1/recurring/contracts/algorand/spending_cap_vault_v1
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- new endpoint: GET /mandate/portal/{mandate_id}
- new endpoint: POST /mandate/portal/{mandate_id}/topup/capture
- new endpoint: POST /mandate/portal/{mandate_id}/topup/initiate
- document hash changed (no semantic differences detected)
- new endpoint: POST /mandate/pay
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- new endpoint: GET /mpp/sub/{resource_id}
- new endpoint: POST /mpp/sub/{resource_id}
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
- document hash changed (no semantic differences detected)
Scan snapshots
| Date | Grade | Score | Response | Status |
|---|---|---|---|---|
| 2026-05-11 | D | 48% | 674ms | Up |
| 2026-05-12 | D | 48% | 132ms | Up |
| 2026-05-13 | D | 48% | 141ms | Up |
| 2026-05-14 | D | 48% | 141ms | Up |
| 2026-05-15 | D | 48% | 136ms | Up |
| 2026-05-16 | D | 48% | 128ms | Up |
| 2026-05-17 | D | 48% | 126ms | Up |
| 2026-05-18 | D | 48% | 432ms | Up |
| 2026-05-19 | D | 48% | 114ms | Up |
| 2026-05-20 | D | 48% | 155ms | Up |
| 2026-05-21 | D | 48% | 145ms | Up |
| 2026-05-22 | D | 48% | 136ms | Up |
| 2026-05-23 | D | 48% | 144ms | Up |
| 2026-05-24 | D | 48% | 195ms | Up |
| 2026-05-25 | D | 48% | 204ms | Up |
| 2026-05-26 | D | 48% | 306ms | Up |
| 2026-05-27 | D | 48% | 140ms | Up |