Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.algovoi.co.uk/llms.txt

Use this file to discover all available pages before exploring further.

The AlgoVoi recurring payment engine is the subsystem responsible for scheduled, pre-authorised payments across all seven supported chains. It supports two distinct recurring payment models — MPP subscription protocol (Tier 1) and standing authorities (Tier 2) — and is accessible at recurr.algovoi.co.uk. Both models share a common pull executor, a common mandate data model, and common integration with the five audit chains. All pull transactions are settled on-chain with full receipt-format emission, making every recurring charge auditable, cancellable, and refundable under the same PSD2-aligned framework as one-off payments.

Architecture Overview

ComponentRole
Recurring engineHosts the MPP subscription endpoint, the standing authority API, and the pull executor scheduler
Control planeMandate creation, activation, state management, safeguard enforcement
Facilitator (active-passive cluster)Chain-specific RPC submission for pull transactions
Audit chainspayment_ledger, compliance_events, and negotiation_trace_events receive a row for every pull
Object Lock storageAll audit rows shipped off-VM within approximately 5 minutes of write
The pull executor runs as a scheduled in-process job. It evaluates next_due_at across all active mandates and standing authorities on a sub-minute cadence and submits pull transactions when due.

Mandate Data Model

Every recurring arrangement — whether a Tier 1 MPP subscription or a Tier 2 standing authority — is represented as a mandate record. The mandate record is the single source of truth for scheduling, cap enforcement, and state management.

Mandate Fields

FieldTypeValues / Description
iduuidPrimary key
tenant_iduuidThe merchant tenant that owns this mandate
resource_idstringThe payable resource this mandate covers; used in MPP subscription URLs
payer_addressstringThe on-chain wallet that authorised the mandate
chainenumalgorand, voi, hedera, stellar, base, solana, or tempo
asset_idstringCAIP-19 asset identifier (e.g. eip155:8453/erc20:0x… for Base USDC)
cap_microunitsbigintMaximum amount per pull execution, in the smallest on-chain denomination
period_unitenumday, week, or month
period_countintegerNumber of period_unit intervals between pulls (e.g. period_count=30, period_unit=day means every 30 days)
mandate_typeenummpp_subscription (Tier 1), standing_authority (Tier 2)
statusenumpending, active, paused, revoked, expired, cancelled
activated_attimestampISO 8601 UTC timestamp when on-chain signature was confirmed by the facilitator
next_due_attimestampISO 8601 UTC timestamp of the next scheduled pull
last_pull_attimestampISO 8601 UTC timestamp of the most recent successful pull
last_pull_tx_idstringOn-chain transaction ID of the most recent pull
cancel_attimestampScheduled cancellation date; null if no scheduled cancellation
cancel_reasonenumuser_requested, merchant_requested, compliance_terminated, expired, or null
per_cycle_microunitsbigintTier 2 only. Maximum amount per pull (may be less than cap_microunits if cap is a lifetime cap)
lifetime_cap_microunitsbigintTier 2 only. Lifetime cap across all pulls under this authority. Null if uncapped.
total_pulled_microunitsbigintRunning total of all amounts successfully pulled under this mandate
created_attimestampISO 8601 UTC creation timestamp
updated_attimestampISO 8601 UTC last-update timestamp

Sealed Audit Fields

The following fields are sealed at insert into the payment_ledger audit chain on every pull and cannot be altered retrospectively: tenant_id, resource_id, tx_id (per pull), chain, asset_id, amount_microunits (per pull), payer_address, verified_at, status, protocol (recurr)

Platform Safeguards

The following limits are enforced at the control plane level for all mandate types. They are not configurable at tenant level.
SafeguardLimitEnforcement
Per-mandate cap£100 maximum cap_microunits (in GBP equivalent at activation time)Enforced at mandate creation; mandate rejected if cap exceeds limit
Per-account total cap£300 maximum sum of active mandate caps per payer accountEnforced at mandate creation; mandate rejected if it would cause the account total to exceed the limit
Maximum concurrent mandates3 active mandates per payer accountEnforced at mandate creation; mandate rejected if the payer already has 3 active mandates
These limits are aligned with EMR 2011 Regulations 20–21 safeguarding requirements for payment institutions holding funds on behalf of customers. PSD2-aligned behaviour: when a mandate is cancelled with cancel_reason = user_requested, a cancellation receipt is emitted automatically per draft-hopley-x402-cancellation-receipt. This satisfies PSD2 Article 64 requirements for the customer’s right to revoke a payment authorisation.

Mandate Lifecycle State Machine

Mandates move through states according to the following transitions. No transition is possible outside this defined state machine.

States

StateDescription
pendingMandate record created; awaiting on-chain wallet signature confirmation
activeOn-chain signature confirmed by facilitator; pulls scheduled
pausedPulls suspended; no on-chain action required; resumes on operator or tenant action
revokedPayer revoked the on-chain authorisation; facilitator detected revocation; no further pulls
expiredcancel_at timestamp reached; no further pulls
cancelledOperator or tenant cancelled with an explicit cancel_reason; cancellation receipt emitted

Transitions

FromToTriggerSide Effects
pendingactiveFacilitator confirms on-chain wallet signatureactivated_at set; next_due_at calculated; compliance_events row written
activepausedTenant or operator pausesnext_due_at preserved but not acted on; compliance_events row written
pausedactiveTenant or operator resumesnext_due_at recalculated from resume time or preserved (configurable); compliance_events row written
activerevokedFacilitator detects on-chain revocationNo further pulls; mandate.revoked webhook emitted; compliance_events row written
activeexpiredcancel_at reachedNo further pulls; mandate.expired webhook emitted; compliance_events row written
pausedexpiredcancel_at reached while pausedAs above
activecancelledTenant or operator cancelscancel_reason set; cancellation receipt emitted; mandate.cancelled webhook emitted
pausedcancelledAs aboveAs above
pendingcancelledMerchant cancels before activationNo cancellation receipt (no payment was authorised)

Tier 1: MPP Subscription Protocol

The Merchant Payment Protocol (MPP) subscription model is the standard recurring payment flow for merchants integrating with payer applications, AI agents, and wallets that support the paymentauth.org/mpp method string.

Resource Registration

A subscription resource is registered by the merchant at a deterministic URL: POST /mpp/sub// Where tenant_short_id is the merchant’s short identifier (visible in the dashboard) and resource_id is the merchant’s internal identifier for the subscription offering (e.g. a plan ID or product slug).

Subscription Intent Flow

  1. An agent or payer issues a GET or POST to the subscription resource URL.
  2. The Recurr service responds with HTTP 402 Payment Required and a subscription intent body.
  3. The payer application reads the intent body and presents the subscription offer to the end user.
  4. The payer signs a standing authority credential on-chain for the requested resource.
  5. The facilitator confirms the on-chain signature to the control plane.
  6. The mandate transitions from pending to active.
  7. The pull executor charges the payer at each due date by constructing and submitting the on-chain pull transaction through the facilitator.

Subscription Intent Body Fields

FieldTypeDescription
typestringFixed value: mpp_subscription
resourceIdstringThe resource_id this subscription covers
amountstringDisplay amount (e.g. “10.00 USDC”)
amount_microunitsbigintAmount in smallest on-chain denomination
assetstringAsset ticker
asset_idstringCAIP-19 asset identifier
networkstringTarget chain in paymentauth.org network string format
period_unitenumday, week, or month
period_countintegerNumber of period_unit intervals between pulls
methodstringFixed value: paymentauth.org/mpp
merchant_namestringDisplay name of the merchant
descriptionstringHuman-readable description of the subscription
expirestimestampISO 8601 UTC expiry of this intent offer
signing_endpointstringURL to which the payer submits the on-chain signature credential

MPP Subscription Status Fields

FieldTypeDescription
subscription_iduuidThe mandate id for this subscription
resource_idstringThe subscribed resource
statusenumactive, paused, revoked, or expired
activated_attimestampWhen subscription activated
first_pull_tx_idstringOn-chain tx_id of the first pull
first_pull_finalized_attimestampTimestamp of first pull confirmation
next_due_attimestampNext scheduled pull
last_pull_attimestampMost recent successful pull
last_pull_tx_idstringOn-chain tx_id of most recent pull
total_pulled_microunitsbigintRunning total pulled under this subscription

MPP Webhook Events

EventTrigger
mpp_subscription.activatedOn-chain signature confirmed; subscription moves to active
mpp_subscription.chargedPull transaction confirmed on-chain
mpp_subscription.charge_failedPull attempt failed after full retry schedule
mpp_subscription.revokedPayer revoked on-chain authorisation
mpp_subscription.expiredcancel_at reached

Tier 2: Standing Authorities

Tier 2 standing authorities are a higher-autonomy variant for AI-agent payment scenarios. A customer authorises a spending cap once. The agent or automated system then pulls payments on schedule against that cap without requesting re-authorisation for each individual pull.

Additional Fields (Tier 2 Only)

FieldTypeDescription
per_cycle_microunitsbigintMaximum amount per individual pull. May be less than cap_microunits.
lifetime_cap_microunitsbigintLifetime total cap. Null if only per-cycle capping applies.
pull_modeenumscheduled (automatic on next_due_at) or on_demand (only fires on explicit API call)
last_manual_pull_attimestampTimestamp of last pull triggered via the manual pull endpoint

Manual Pull Endpoint

POST /v1/recurring//pull Triggers an immediate on-demand pull against a standing authority with pull_mode = on_demand. The pull is subject to per_cycle_microunits and the remaining lifetime cap. The request accepts an optional amount_microunits override (must be less than or equal to per_cycle_microunits). Response fields:
FieldTypeDescription
pull_iduuidIdentifier for this specific pull attempt
tx_idstringOn-chain transaction ID (present once submitted; may be pending_confirmation)
amount_microunitsbigintAmount pulled
statusenumsubmitted, confirmed, failed
submitted_attimestampWhen the pull transaction was submitted to the chain
confirmed_attimestampWhen the pull transaction was confirmed (null if pending)

Tier 2 Chain Support

Tier 2 standing authorities are available on chains where the on-chain signature mechanism supports the required pre-authorisation credential format:
ChainTier 2 Authority Support
AlgorandSupported
VOISupported
BaseSupported
SolanaSupported
HederaNot currently supported
StellarNot currently supported
TempoNot currently supported

Pull Executor

The pull executor is the in-process scheduler that drives all recurring charges. It runs on the recurring payment engine.

Scheduling

The executor runs on a sub-minute cadence. On each tick it queries for all active mandates (both Tier 1 and Tier 2 scheduled) where next_due_at is in the past and status is active. Each due mandate is processed in order of next_due_at ascending.

Per-Pull Execution Steps

For each due mandate, the executor performs the following steps in order:
  1. Validate mandate state: confirm status is still active (it may have been revoked between ticks).
  2. Check safeguards: confirm that the pull amount does not exceed cap_microunits. For Tier 2 authorities, also confirm that the pull would not exceed lifetime_cap_microunits.
  3. Construct pull transaction: build the chain-appropriate pull transaction. The transaction construction is delegated to the chain-specific facilitator module. The constructed transaction includes the on-chain reference to the standing authority credential.
  4. Submit to facilitator: POST the raw transaction to the facilitator (active-passive cluster; standby instance used if primary is unreachable). The facilitator signs and broadcasts to the chain RPC.
  5. Await confirmation: poll for on-chain confirmation up to the chain-specific timeout.
  6. On success:
    • Update last_pull_at and last_pull_tx_id on the mandate record
    • Increment total_pulled_microunits
    • Calculate and store the new next_due_at
    • Write a payment_ledger audit chain row
    • Write a negotiation_trace_events row with event_type = mandate_activated (for first pull) or subscription_charged
    • Emit mandate.charged or mpp_subscription.charged webhook event
    • Emit a settlement_attestation receipt (per draft-hopley-x402-settlement-attestation)
  7. On confirmation failure (chain timeout or RPC error):
    • Record the failed attempt with failure_reason and attempt_count
    • Schedule a retry per the pull-retry schedule (see below)
  8. On final failure (all retries exhausted):
    • Set pull_failed_at and pull_failure_reason on the mandate record
    • Emit mandate.charge_failed or mpp_subscription.charge_failed webhook event
    • next_due_at is advanced to the next period (the missed period is not retried indefinitely)
    • Write a negotiation_trace_events row with event_type = rejected and outcome_reason = pull_failure

Pull-Retry Schedule

AttemptDelay Before Retry
1 (initial)Immediate
230 seconds
35 minutes
430 minutes
52 hours
6 (final)8 hours
After six failed attempts, the pull is marked as permanently failed for that period. The mandate remains active; the next period’s pull will be attempted at next_due_at.

Failover

The pull executor submits through the facilitator API. If the primary facilitator is unreachable, the executor retries against the standby instance.

Receipt Chain Integration

Every mandate pull emits a full receipt suite. Receipts are formatted per the AlgoVoi IETF Internet-Draft suite, canonicalised via RFC 8785 JCS, and written to the appropriate audit chains.

Receipts Emitted Per Pull

Receipt TypeInternet-DraftTriggerKey Fields
Settlement attestationdraft-hopley-x402-settlement-attestationEvery confirmed pullsettlement_status (SETTLED / PENDING_FINALITY / REVERSED), tx_id, chain, asset_id, amount_microunits, settled_at
Cancellation receiptdraft-hopley-x402-cancellation-receiptOn mandate cancellation or revocationcancellation_reason (USER_REQUESTED / MERCHANT_REQUESTED / COMPLIANCE_TERMINATED / EXPIRED), cancelled_at, payer_address
Refund receiptdraft-hopley-x402-refund-receiptWhen a PSD2 refund is owedrefund_type (FULL / PARTIAL / REJECTED), refund_amount_microunits, original_tx_id, refund_tx_id

Audit Chain Rows Per Pull

ChainRow WrittenWhen
payment_ledgerOne row per confirmed pullAt pull confirmation
negotiation_trace_eventsOne row per pull attempt (success or failure)At submission and at outcome
compliance_eventsOne row per state transitionWhen mandate status changes (activation, pause, revoke, cancel, expire)
All rows are hash-chained and shipped to off-VM COMPLIANCE-mode Object Lock storage within approximately five minutes of write.

API Endpoints

Mandate Management

MethodPathDescription
POST/v1/mandatesCreate a new mandate. Returns mandate_id and the on-chain signing URL.
GET/v1/mandatesList all mandates for the authenticated tenant
GET/v1/mandates/Get mandate detail including pull history
POST/v1/mandates//pausePause an active mandate
POST/v1/mandates//resumeResume a paused mandate
POST/v1/mandates//cancelCancel a mandate; cancel_reason required in body

Standing Authorities (Tier 2)

MethodPathDescription
POST/v1/recurringCreate a new standing authority
GET/v1/recurringList all standing authorities for the tenant
GET/v1/recurring/Get authority detail and pull history
POST/v1/recurring//pullTrigger an on-demand pull
POST/v1/recurring//pausePause
POST/v1/recurring//resumeResume
POST/v1/recurring//cancelCancel

MPP Subscription (Tier 1)

MethodPathDescription
GET or POST/mpp/sub//Returns 402 with subscription intent body if no active subscription; returns 200 with subscription status if already subscribed
POST/mpp/sub///signReceives the on-chain signature credential from the payer application
GET/mpp/sub///statusReturns subscription status fields

Live Demo Resource

A live MPP subscription fixture is available at: GET /mpp/sub/demo/mpp-sub-test-daily-base This resource is permanently maintained and can be used by integration partners to test MPP subscription flows against the live Recurr service without creating a tenant account. It uses Base chain USDC. Do not delete this resource.

Chain Coverage

ChainTier 1 MPP SubscriptionTier 2 Standing AuthorityMandate (basic)
AlgorandSupportedSupportedSupported
VOISupportedSupportedSupported
HederaSupportedNot supportedSupported
StellarSupportedNot supportedSupported
BaseSupportedSupportedSupported
SolanaSupportedSupportedSupported
TempoSupportedNot supportedSupported
Algorand, VOI, Base, and Solana have the richest recurring support because their on-chain authorisation credential formats support the pre-authorisation capability required for Tier 2 pull semantics. Hedera, Stellar, and Tempo support Tier 1 and basic mandates via a challenge-response model per pull.

Integration with Broader Protocol Suite

The Recurr engine participates in the AlgoVoi multi-protocol payment stack alongside x402, AP2, A2A, and hosted checkout. All five protocols share:
  • The same payment_ledger audit chain (every confirmed payment from any protocol appears in the same chain)
  • The same receipt-format suite (settlement attestation, compliance receipt, cancellation receipt, refund receipt)
  • The same compliance engine (every payer address screened on every mandate activation and every pull)
  • The same facilitator architecture (pull transactions submitted through the active-passive facilitator cluster)
Protocol field in payment_ledger rows distinguishes recurr payments from checkout, x402, mpp, ap2, and a2a payments. All protocol rows are hash-chained together in a single payment_ledger chain, not in separate per-protocol chains.

Regulatory Alignment

FrameworkAlignment
PSD2 Article 64 (right to revoke recurring payment authorisation)Addressed: user_requested cancellation emits cancellation receipt; mandate revoked on facilitator detection of on-chain revocation
PSD2 Article 89 (refund obligations)Addressed: refund receipt format available; refund_type = FULL / PARTIAL / REJECTED
EMR 2011 Regulations 20–21 (safeguarding)Live: £100/mandate, £300/account, 3 mandate caps enforced at control plane level
UK MLRs 2017 Regulation 40 (transaction record-keeping)Addressed: payment_ledger rows in COMPLIANCE-mode Object Lock to 2033
MiCA Art. 80 / AMLR Art. 56 (crypto-asset record-keeping)Addressed: settlement attestation covers record-keeping field requirements