Recivanta is a white-label invoice discounting (TReDS) marketplace: suppliers sell approved invoices owed by large anchor buyers to competing financiers who bid a discount rate. This API is how an anchor buyer's ERP, a supplier's accounting system, a financier's trading desk, a settlement bank or custodian, or an auditor integrates with a tenant running on Recivanta — participant onboarding and KYC, programme and membership management, invoice (Factoring Unit) registration and lifecycle, the bidding engine and order book, settlement instructions, fee schedules and quotes, and public blockchain anchor verification.
Every resource below is a real Go package in backend/internal/ with its own HTTP handlers, tested
against a live, row-level-secured Postgres database — not a mocked scaffold. The full field-level detail
for every one of these lives in the interactive reference.
WebAuthn passkeys, TOTP, step-up re-authentication, session logout. The endpoints that get you a bearer token.
Organisation onboarding and KYC lifecycle — supplier, buyer, financier, developer, settlement bank, custodian — with maker-checker approval.
Anchor-buyer programme setup, limit governance, and supplier membership / opt-in lifecycle.
Factoring Unit registration and its 12-state lifecycle, with duplicate-financing detection across tenants.
The order book, bid placement, withdrawal, and bid acceptance — the step that creates a trade.
Funding instructions and the five-step maturity waterfall, behind a step-up gate for every money movement.
Maker-checker-gated fee schedules and the quote / late-fee / simulation calculators built on them.
The one genuinely public endpoint: independently verify a record's Bantu blockchain anchor. No account required.
Every endpoint except anchor verification requires Authorization: Bearer <token>. Here's the
honest version of how to get one against the API as it exists right now — not the self-service
application/API-key flow the long-term specification describes, which isn't built yet.
Two real login paths exist today:
POST /v1/auth/passkey/login/begin then
/finish, driven from a real browser's navigator.credentials API. This is the
production path for a human user.POST /v1/auth/totp/verify-login with a user id
and a confirmed TOTP code. Honest caveat: password verification isn't built anywhere in this codebase
yet, so this is really a second factor standing in for a full login, not a complete password+TOTP
flow. It still mints a real bearer session.Both pre-authentication endpoints require an X-Tenant-ID header identifying your tenant
— a deliberate, narrow stand-in until hostname-based tenant resolution is wired up at the
gateway.
curl -X POST https://api.nse.recivanta.com/v1/auth/totp/verify-login \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: nse" \
-d '{"user_id": "usr_01HZX...", "code": "482913"}'
→ { "token": "ey...", "expires_at": "2026-11-07T18:30:00Z" }
Use token as Authorization: Bearer <token> on every subsequent call.
Accepting a bid, instructing funding, distributing a maturity waterfall, and a few other money-moving
endpoints additionally require a step-up session. If you get back
403 STEP_UP_REQUIRED, call POST /v1/auth/step-up/require, then
POST /v1/auth/step-up/complete with a fresh TOTP code, and use the token it returns for the
gated call.
curl https://api.nse.recivanta.com/v1/participants \
-H "Authorization: Bearer ey..."
Every endpoint, request shape, and error code is documented in the interactive reference, generated from openapi.json.
POST /v1/auth/dev/login endpoint exists in
the backend to bootstrap a first session against the seeded synthetic demo tenant without a credential check
— it is disabled by default (requires the server's ALLOW_DEV_LOGIN=true) and only ever
works against tenants explicitly flagged as synthetic demo data. It is documented in the reference for
completeness, not as a general-purpose credential.
The same rules apply everywhere in the API — the full detail is in the reference, this is the cheat sheet.
{"amount_minor": 12500000, "currency": "KES"} — integer minor units plus an ISO 4217 code. Never a float.application/problem+json: {type, title, status, detail, code, errors[], meta}. code is the stable value to branch on.inv_01HZX..., bid_01HZX..., trd_01HZX.... Never a bare UUID or integer.Authorization: Bearer <token> on every endpoint except POST /v1/anchors:verify and the pre-authentication identity endpoints.404, never 403 — existence is never leaked across tenants.Idempotency-Key header) on exactly one endpoint today: accepting a bid. Not yet enforced on other writes, even though that's the long-term intent.limit/offset, invoices uses limit only. No cursor pagination is implemented yet anywhere.Initial published API surface, documented directly from the running backend.
This is a true first cut, not a curated highlight reel — there is no prior version to compare against. Future entries will describe real additive changes as they ship.