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 Control Plane is the management backend for all tenant configuration and lifecycle operations. It owns the authoritative state for every tenant, their compliance status, their API credentials, their webhook destinations, and their payment authority configuration. The control plane is not involved in the per-payment verification path — that responsibility belongs to the gateway and facilitator — but every tenant capability that the gateway exercises (API key validation, KYC gating, trial balance enforcement, mandate lookup) is sourced from state owned by the control plane. The control plane runs co-located with the gateway and exposes 212 or more routes. It serves both the Dashboard React SPA at dash.algovoi.co.uk and a programmatic REST API available to tenants and admin operators.

Overview

PropertyValue
Base URLhttps://api.algovoi.co.uk (shared with gateway)
Route count212+
LocationPrimary compute node (co-located with gateway)
Dashboarddash.algovoi.co.uk (React SPA, same VM, nginx)
Owned stateTenant config, KYC/KYB, API keys, webhooks, mandates, recurring authorities
EncryptionThree-family at-rest encryption for KYC documents, KYB documents, and operational data (separate key families, independently rotated)
Admin surface/admin/* endpoints; 14 admin scopes; MLRO review queue

Tenant onboarding flow

Tenant onboarding is a six-stage process that gates mainnet payment processing behind identity verification. The stages are sequential; each stage must complete successfully before the next becomes available. Stage 1 — Account creation. POST /cloud-signup/create accepts email, password, and display_name. The IP address of the signup request is synchronously screened against three threat signals: Tor exit node lists, SpamHaus blocklists, and MaxMind GeoIP country classification. If the IP fails screening, registration is rejected before any account record is created. Stage 2 — Email verification. A time-limited verification token is sent to the submitted email address. The account is created but remains in inactive status until POST /cloud-signup/verify-email is called with the token. Unverified accounts cannot authenticate. Stage 3 — KYC document submission. After email verification, the tenant submits identity documents via POST /v1/kyc/submit. Accepted document types are passport, driving_licence, and national_id. A selfie image must accompany any identity document. All uploaded files are encrypted at rest immediately on receipt using the platform’s document encryption key before being written to persistent storage. The plaintext file is never written to disk. Stage 4 — KYC decision. For individual and sole_trader account types, KYC is evaluated by automated document verification (OCR Tier 1) and auto-approved if document quality and consistency checks pass. For company account types, the submission lands in the MLRO review queue and requires manual review by an admin operator. The tenant receives a kyc.approved or kyc.rejected webhook event when the decision is made. Stage 5 — Mainnet activation. On KYC approval, mainnet_active is set to true and trial_balance_usd is credited with 100000000 microunits ($1,000.00 USD equivalent). The tenant can now process live payments on mainnet. The trial balance decrements on each verified mainnet payment; when trial_exhausted becomes true, continued live payments require a paid plan. Stage 6 — KYB (conditional). Company tenants or tenants whose risk scoring produces an elevated risk tier receive a KYB (Know Your Business) requirement. POST /v1/kyb/submit accepts company registration documents, beneficial owner declarations, and proof of address. KYB documents are encrypted with a separate key family, isolated from the platform key and the KYC key. KYB is evaluated by the MLRO queue regardless of company size.

Tenant data model

FieldTypeDescription
iduuidPrimary key
tenant_short_idstringURL-safe short identifier used in MPP subscription paths and discovery catalog entries
emailstringUnique; verified before activation
display_namestringMerchant or platform display name
account_typeenumindividual, sole_trader, company
kyc_statusenumpending, submitted, approved, rejected
kyb_statusenumpending, submitted, approved, rejected, not_required
risk_tierenumstandard, elevated, high, blocked
mainnet_activebooleanTrue only after KYC decision is approved
trial_balance_usdintegerRemaining trial credit in microunits (1 = $0.000001)
trial_exhaustedbooleanTrue when trial_balance_usd reaches zero
planenumtrial, standard, enterprise
signup_ipstringIP address recorded at registration (for audit trail)
email_verifiedboolean
email_verified_atstringISO-8601 timestamp of email verification
kyc_submitted_atstringISO-8601 timestamp of KYC document submission
kyc_decided_atstringISO-8601 timestamp of KYC approval or rejection
kyb_submitted_atstringISO-8601 timestamp of KYB submission if applicable
kyb_decided_atstringISO-8601 timestamp of KYB decision if applicable
mainnet_activated_atstringISO-8601 timestamp of mainnet activation
created_atstringISO-8601 creation timestamp
updated_atstringISO-8601 last-update timestamp

Risk tier effects

risk_tierEffect
standardDefault; full platform access
elevatedRequires completed KYB before high-value payments
highTransaction velocity limits applied; manual review on large payouts
blockedAccount suspended; no payment processing; MLRO intervention required
Risk tier is set by the MLRO at any time. Tenants are not notified of their specific tier — they receive only the operational consequences (e.g. a KYB requirement prompt).

API key management

API keys authenticate tenant API calls to both the gateway and the control plane. Keys are created, scoped, and revoked through the control plane.

Key types

PrefixTypeCapability
algv_StandardFull tenant-scoped access; all payment operations
algv_admin_Admin14 admin scopes; tenant management, MLRO queue, risk tier override
algv_ro_Read-onlyGET operations only; no resource creation or modification

Key lifecycle endpoints

EndpointMethodDescription
/v1/api-keysPOSTCreate a new key
/v1/api-keysGETList all keys for the authenticated tenant
/v1/api-keys/GETRetrieve key metadata (not the key value)
/v1/api-keys/DELETERevoke a key immediately

Key creation fields

FieldTypeRequiredDescription
namestringYesHuman-readable label for the key
scopesarray of stringNoExplicit scope list; defaults to all tenant-level scopes
expires_atstringNoISO-8601 expiry; key is auto-revoked at this time
The full key value is returned once in the creation response and never again. The control plane stores only a SHA-256 hash of the key. If the key value is lost, it must be revoked and a new key created. Multi-key rotation. A tenant may hold multiple active keys simultaneously. During a rotation, the old key remains valid while the new key is adopted across integrations. The old key should be explicitly revoked via DELETE /v1/api-keys/{id} once migration is complete.

Admin scopes

Admin keys (algv_admin_) have access to 14 scopes not available to standard keys:
ScopeCapability
read:tenantsRead all tenant records
write:tenantsModify tenant fields including risk_tier and mainnet_active
read:kyc_queueRead pending KYC submissions in the MLRO queue
write:kyc_decisionsApprove or reject KYC submissions
read:kyb_queueRead pending KYB submissions
write:kyb_decisionsApprove or reject KYB submissions
read:audit_chainRead payment_ledger and screening_hits chains
read:screening_hitsRead all sanctions screening hit records
write:risk_tierOverride tenant risk tier
read:mandates_allRead all mandates across all tenants
write:mandate_cancelCancel mandates on compliance grounds
read:recurring_allRead all recurring authorities across all tenants
write:trial_balanceAdjust trial balance credits
read:admin_eventsRead admin action audit log

Webhook configuration

Tenants register webhook endpoints to receive platform events. The control plane manages endpoint registration, screening, and delivery.

Endpoint registration

POST /v1/webhooks
FieldTypeRequiredDescription
urlstringYesHTTPS destination URL
eventsarray of stringYesEvent types to subscribe to; use [”*”] for all events
secretstringNoShared secret for HMAC signature; auto-generated if omitted
descriptionstringNoHuman-readable label
activebooleanNoDefaults to true
URL screening at registration. Before a webhook URL is saved, the control plane evaluates it against:
  • SSRF guard: private IP ranges, localhost, and link-local addresses are rejected
  • 7 threat-intel feeds: same feeds used for IP screening at signup
  • DNS resolution: the hostname must resolve at registration time
DNS-rebinding guard at delivery. At every webhook delivery attempt, the destination hostname is re-resolved. If the resolved IP has changed to a private range since registration, the delivery is aborted and a webhook.delivery_blocked.dns_rebinding event is recorded on the endpoint.

Delivery retry schedule

AttemptDelay after previous
1 (immediate)0s
230s
31m
45m
515m
630m
71h
84h
932h
After 9 failed attempts the endpoint is marked degraded. The tenant receives a webhook.endpoint.degraded notification to the next reachable endpoint (or email if all endpoints are degraded). Endpoints can be re-activated via PATCH /v1/webhooks/{id} with { "active": true }.

Webhook event catalog

The full set of 18 subscribable event types:
Event typeCategory
payment.verifiedPayment
payment.pending_finalityPayment
payment.blocked.compliancePayment
payment.expiredPayment
checkout.createdCheckout
checkout.cancelledCheckout
mandate.createdMandate
mandate.activatedMandate
mandate.pausedMandate
mandate.resumedMandate
mandate.revokedMandate
mandate.expiredMandate
mandate.cancelledMandate
recurring.pull_executedRecurring
recurring.pull_failedRecurring
kyc.approvedAccount
kyc.rejectedAccount
compliance.sanctions_hitCompliance

Mandate lifecycle

A mandate represents an on-chain payment authority granted by a payer to a merchant. The control plane owns the mandate record; the gateway and Recurr service read from it.

Mandate states

StateDescription
pendingMandate record created; payer has not yet provided on-chain wallet signature
activeOn-chain wallet signature confirmed; pull executions are permitted
pausedPulls suspended by the tenant or the payer; mandate remains valid; can be resumed
revokedPayer revoked the mandate on-chain; no further pulls possible
expiredReached the cancel_at timestamp without earlier revocation
cancelledCancelled via platform API; cancel_reason set

State transitions

FromToTrigger
pendingactiveGateway confirms on-chain wallet signature
activepausedTenant calls PATCH /v1/mandates/ with status: paused
pausedactiveTenant calls PATCH /v1/mandates/ with status: active
activerevokedOn-chain revocation detected by gateway
activeexpiredScheduled job detects cancel_at reached
active or pausedcancelledTenant calls DELETE /v1/mandates/ or admin invokes write:mandate_cancel

Cancellation reasons

cancel_reasonSource
user_requestedPayer initiated cancellation
merchant_requestedTenant initiated cancellation
compliance_terminatedAdmin cancelled on sanctions or risk-tier grounds
expiredSystem-generated on cancel_at breach

Mandate data model

FieldTypeDescription
iduuidPrimary key
tenant_iduuidOwning tenant
payer_walletstringOn-chain wallet address of the mandate grantor
chainenumChain the mandate operates on
cap_microunitsbigintMaximum single-pull amount
cancel_atstringISO-8601 timestamp after which the mandate expires
statusenumpending, active, paused, revoked, expired, cancelled
cancel_reasonenumPopulated on cancellation
on_chain_tx_idstringTransaction ID of the wallet signature confirmation
created_atstringISO-8601 creation timestamp
activated_atstringISO-8601 activation timestamp
cancelled_atstringISO-8601 cancellation timestamp

EMR safeguards

The following safeguards are enforced at the control plane level on all mandates, regardless of the stated cap. They cannot be overridden by tenant configuration:
SafeguardValue
Maximum per-mandate cap£100 equivalent
Maximum total active mandate value per account£300 equivalent
Maximum active mandates per account3
These limits implement EMR 2011 regulation 20-21 safeguarding requirements for e-money and agent-initiated payment flows.

Recurring payment authorities (Tier 2)

Recurring authorities are standing payment permissions that allow AI agents or automated systems to initiate time-based pulls against a payer wallet without per-pull interaction. They are managed by the control plane and executed by the recurring payment engine.

Authority data model

FieldTypeDescription
iduuidPrimary key
mandate_iduuidParent mandate this authority operates under
tenant_iduuidOwning tenant
per_cycle_microunitsbigintAmount pulled per execution cycle
cap_microunitsbigintCeiling on any single pull (may not exceed parent mandate cap)
period_unitenumday, week, month
period_countintegerNumber of period_unit intervals per cycle
statusenumpending_signature, active, paused, cancelled, exhausted
total_pulled_microunitsbigintCumulative amount pulled since activation
lifetime_cap_microunitsbigintOptional total lifetime cap; authority exhausted when reached
next_execution_atstringISO-8601 scheduled next pull time
on_chain_tx_idstringTransaction ID of the on-chain authority signature
created_atstringISO-8601 creation timestamp
activated_atstringISO-8601 activation timestamp

Authority lifecycle

POST /v1/recurring-authorities creates a new authority in pending_signature state. The on-chain wallet signature must be obtained and confirmed before the authority moves to active. Signature confirmation follows the same flow as mandate activation — the gateway detects the on-chain signature and updates the authority status. Once active, the Recurr service executes pulls on the schedule defined by period_unit and period_count. Each pull produces a recurring.pull_executed or recurring.pull_failed webhook event. Manual pull. POST /v1/recurring-authorities/{id}/execute triggers an immediate out-of-schedule pull. This supports catch-up after a missed cycle or proration scenarios. The manual pull respects all the same caps as a scheduled pull. Pause and resume. PATCH /v1/recurring-authorities/{id} with { "status": "paused" } suspends scheduled pulls without requiring a new on-chain signature. { "status": "active" } resumes from the next scheduled cycle. The authority’s next_execution_at is recalculated on resume. Exhaustion. When total_pulled_microunits reaches lifetime_cap_microunits, the authority status is set to exhausted and no further pulls are attempted. The tenant receives a recurring.pull_failed event with reason lifetime_cap_reached.

MLRO admin queue

The MLRO (Money Laundering Reporting Officer) queue is the manual review surface for KYC and KYB submissions that require human examination. It is accessible only to users authenticated with an admin-scoped key carrying the relevant admin scopes.

KYC queue

GET /admin/kyc/queue returns all pending KYC submissions sorted by submitted_at. Each queue item includes:
FieldTypeDescription
tenant_iduuidSubmitting tenant
display_namestringTenant display name
account_typeenumindividual, sole_trader, company
document_typeenumpassport, driving_licence, national_id
submitted_atstringISO-8601 submission timestamp
ocr_resultobjectOCR extraction summary (name, document_number, expiry)
ocr_confidencefloat0.0–1.0 confidence score from OCR Tier 1
auto_approve_eligiblebooleanTrue if criteria are met for auto-approval
risk_signalsarray of stringAny pre-screening signals that flagged the submission
POST /admin/kyc/{tenant_id}/approve approves the submission and triggers mainnet activation. POST /admin/kyc/{tenant_id}/reject rejects with a required reason field. Both actions generate the corresponding webhook event to the tenant.

KYB queue

GET /admin/kyb/queue returns pending KYB submissions. KYB submissions always require manual review regardless of company size. The queue item includes beneficial owner declarations, company registration document references, and a risk score from the KYB screening pipeline. POST /admin/kyb/{tenant_id}/approve and POST /admin/kyb/{tenant_id}/reject follow the same pattern as KYC decisions. A KYB rejection does not affect the tenant’s mainnet_active status if it was already true; it applies a risk_tier upgrade to elevated or high depending on the rejection grounds.

Admin event log

All admin actions (KYC decisions, KYB decisions, risk tier overrides, mandate cancellations, trial balance adjustments) are appended to an immutable admin event log. GET /admin/events returns a paginated log sortable by timestamp. Each event records actor (admin key ID), action, target_tenant_id, before_state, after_state, and timestamp.

KYC and KYB encryption

All identity documents are encrypted before being written to any persistent storage layer. The encryption architecture uses three separate key families to ensure that a compromise of one key does not expose documents of a different class.

Key families

Key familyDocuments encrypted
Document key family 1KYC documents (passports, selfies, driving licences, national IDs)
Document key family 2KYB documents (company registration, beneficial owner declarations, proof of address)
Operational key familyAt-rest operational data
Every encrypted file carries an in-band header encoding the key family identifier. The decryption loader verifies the header matches the expected key family before attempting decryption. A file presented to the wrong loader is rejected before any decryption is attempted.

Zero-downtime key rotation

The platform supports zero-downtime key rotation. At any point a key family may have two active tokens: the current token (used for all new encryptions) and the previous token (honoured for decryption of files encrypted under the old key). Background re-encryption of existing files completes silently without any application-layer downtime. Once re-encryption is complete, the old token is retired from the decryption stack.

Key loss consequences

Loss of any document encryption key renders the associated encrypted files irrecoverable. Key material is stored outside the codebase in a secrets store isolated from the application layer.

Dashboard API surface

The control plane’s API is the backend for the Dashboard React SPA. The dashboard surfaces the following management areas:
Dashboard areaAPI namespaceDescription
Account overview/v1/account/*Tenant profile, KYC/KYB status, mainnet activation state
Payment history/v1/payments/*All verified payments, filterable by chain, date, status
Payment links/v1/payment-links/*Checkout creation, retrieval, status, cancellation
API keys/v1/api-keys/*Key creation, listing, revocation
Webhooks/v1/webhooks/*Endpoint registration, event log, retry status
Mandates/v1/mandates/*Mandate listing, detail, pause, cancel
Recurring authorities/v1/recurring-authorities/*Authority management, pull history, manual execute
Compliance/v1/compliance/*Screening log, audit chain position, trial balance
xChain/v1/xchain/*Cross-chain transfer history
Admin/admin/*MLRO queue, tenant management, admin event log (admin keys only)

Trial offer

Newly mainnet-activated tenants receive a trial credit of 100000000 microunits ($1,000.00 USD equivalent). The trial balance is decremented by the USD-equivalent of each verified mainnet payment. When the balance reaches zero, trial_exhausted is set to true. Tenants on the trial plan with an exhausted balance must upgrade to standard or enterprise to continue live payment processing. Trial balance state is read by the gateway on every payment verification request. If trial_exhausted is true and plan is trial, the gateway returns 402 Payment Required with error code trial_exhausted before dispatching to the facilitator. The trial offer does not apply to testnet payments. Testnet payments do not consume trial balance and do not create audit chain entries.

Recurr service integration

The recurring payment engine reads recurring authority schedules from the control plane database. It is responsible for:
  • Evaluating which authorities have a next_execution_at in the past and are in active status
  • Submitting pull transactions to the relevant chain
  • Updating next_execution_at and total_pulled_microunits after each successful pull
  • Emitting recurring.pull_executed or recurring.pull_failed events
The Recurr service does not expose an external HTTP API. It is triggered on a schedule and interacts with the control plane via database reads and writes. Manual pull requests from the POST /v1/recurring-authorities/{id}/execute endpoint are queued in the database and picked up by the Recurr service at its next polling interval. The recurring payment engine operates across all 7 supported chains. Pull execution on EVM chains (Base, Tempo) requires funded hot wallets.