Ambit Rail API · v0.1.0-draft

Regulated AUD⇄USDT conversion desk — AUD corridor endpoint for partners.

Spec-first draft — honest status

This documentation is generated from our OpenAPI definition and published ahead of implementation. The sandbox program is opening; endpoints are not yet live in production. Docs are public — production keys are issued only after partner KYB and a signed agreement. The API adds no capability beyond our internal kernel: it can create intents, and the final money-moving step always remains behind an internal maker-checker approval on the Australian side.

Quickstart (sandbox preview)

Deterministic mock rails, self-serve keys, resettable data. Base URL: https://sandbox.api.ambitrail.com/v1

# 1 — create a customer, start hosted KYC
curl -X POST $BASE/customers \
  -H "X-Api-Key: $SANDBOX_KEY" -H "Idempotency-Key: demo-1" \
  -d '{"type":"individual","legal_name":"Ada Lovelace"}'

# 2 — lock a quote (AUD → USDT)
curl -X POST $BASE/quotes \
  -H "X-Api-Key: $SANDBOX_KEY" -H "Idempotency-Key: demo-2" \
  -d '{"customer_id":"cus_…","sell":{"currency":"AUD","minor":100000000,"decimal":"10000.00"},"buy_currency":"USDT"}'

# 3 — create the order, then simulate the AUD deposit in sandbox
#     (magic amount suffixes trigger compliance paths — see below)

# 4 — fetch the attestation receipt and verify it without auth
curl "$BASE/receipts/rcp_…/verify?content_hash=…"

Sandbox scenarios (magic amounts)

Our compliance gates are testable, not hidden. Send a sandbox deposit with the given cents suffix to rehearse each path end-to-end.

.00happy path — matched → posted → order releasable → receipt issued
.13payer name mismatch — deposit suspended_name_mismatch, manual-review queue
.31deposit later reversed — funding_reversed cascades to order/release locks
.77TR data incomplete — release approval blocked_tr_incomplete (fail-closed)

Compliance gates are first-class states

A regulated desk suspends and blocks by design. These appear in order/deposit states and in Problem.compliance_reason — documented, testable, never a surprise:

blocked_kyc_incompleteblocked_kyc_evidence_missingblocked_tr_incompletesuspended_name_mismatchtrading_frozen_by_reconfunding_reversed

Webhook events

Signed envelopes (domain.resource.event), retried with backoff, delivery log queryable.

customer.kyc.updatedva.assigneddeposit.receiveddeposit.matcheddeposit.suspendeddeposit.reversedquote.expiredorder.state.changedorder.releasedorder.settledreceipt.issued

API reference

Generated from openapi.yaml at build time — the spec is the single source of truth. All mutations require an Idempotency-Key header.

customersverify — customer identity, KYC lifecycle (Sumsub-backed)

post/customers

Create a customer (individual or company)

Creates the customer record that all money movement hangs off. KYC ownership model (own-KYC via kyc-session vs reliance on partner KYC) is pending decision Q23 — v0.1 documents the own-KYC flow only.

Response
Customer· errors: Problem (RFC 7807)
get/customers/{customerId}

Fetch a customer

Response
Customer· errors: Problem (RFC 7807)
post/customers/{customerId}/kyc-session

Start a hosted KYC session (Sumsub-backed)

Returns a hosted verification link / SDK token for the end customer. Outcome arrives via `customer.kyc.updated` webhook. Until KYC is GREEN with a verifiable evidence source, all money actions for this customer are fail-closed.

Response
KycSession· errors: Problem (RFC 7807)

virtual-accountssettle — named AUD collection accounts (BSB + account + PayID)

post/virtual-accounts

Issue a named AUD virtual account for a KYC-passed customer

VA is issued in the customer's verified legal name. Deposits from any other payer name will suspend (see Deposit.status). KYC must be GREEN — otherwise 403 `blocked_kyc_incomplete`.

Request
object
Response
VirtualAccount· errors: Problem (RFC 7807)
get/virtual-accounts/{vaId}

Fetch a virtual account

Response
VirtualAccount· errors: Problem (RFC 7807)

quotesquote — locked pricing with expiry

post/quotes

Lock a conversion quote (AUD → USDT)

Locked rate with `expires_at`. Consuming an expired quote fails.

Response
Quote· errors: Problem (RFC 7807)
get/quotes/{quoteId}

Fetch a quote

Response
Quote· errors: Problem (RFC 7807)

orderssettle — quote consumption through to gated release

post/orders

Create an order from a locked quote

Binds quote → expected deposit → gated release. The USDT release step is NEVER triggered by this API: it requires internal maker-checker approval (AU-side). Travel Rule beneficiary data is required before release can be approved (fail-closed, `blocked_tr_incomplete`).

Response
Order· errors: Problem (RFC 7807)
get/orders/{orderId}

Fetch an order

Response
Order· errors: Problem (RFC 7807)

depositssettle — AUD receipts, name-matching states (read-only)

get/deposits

List deposits (read-only)

Response
object· errors: Problem (RFC 7807)
get/deposits/{depositId}

Fetch a deposit

Response
Deposit· errors: Problem (RFC 7807)

receiptsattest — verifiable transaction attestations

get/receipts/{receiptId}

Fetch an attestation receipt

Machine-verifiable record of a completed conversion: amounts, fee waterfall, rate, on-chain tx hash, content hash (+ signature, GA with U1.3/T46).

Response
Receipt· errors: Problem (RFC 7807)
get/receipts/{receiptId}/verifypublic · no auth

Verify a receipt by content hash (PUBLIC — no auth)

Response
object· errors: Problem (RFC 7807)

webhooksevent subscriptions and delivery

get/webhook-endpoints

List webhook endpoints (with delivery log pointers)

Response
object· errors: Problem (RFC 7807)
post/webhook-endpoints

Register a webhook endpoint

Request
object
Response
WebhookEndpoint· errors: Problem (RFC 7807)

Schemas

Problem

RFC 7807. Compliance blocks carry a machine-readable `compliance_reason`.

FieldTypeNotes
type *string
title *string
status *integer
detailstring
compliance_reasonstringenum: blocked_kyc_incomplete · blocked_kyc_evidence_missing · blocked_tr_incomplete · suspended_name_mismatch · trading_frozen_by_recon · funding_reversed

Money

FieldTypeNotes
currency *stringenum: AUD · USDT
minor *integerInteger minor units. AUD: e4. USDT: e6. Never floats.
decimal *stringString decimal mirror for display.

CustomerCreate

FieldTypeNotes
type *stringenum: individual · company
legal_name *stringVA will be issued in this verified name.
emailstring
external_refstringPartner-side customer reference.

Customer

FieldTypeNotes
id *string
kyc_status *stringenum: none · pending · approved · rejected · frozen
kyc_evidence_sourcestringOnly webhook/api-verified evidence unlocks money actions (ADR-16).
created_at *string

KycSession

FieldTypeNotes
session_id *string
verification_url *string
sdk_tokenstring
expires_at *string

VirtualAccount

FieldTypeNotes
id *string
customer_id *string
account_name *stringCustomer's verified legal name — name-match enforced.
bsb *string
account_number *string
payidstring
status *stringenum: active · inactive

QuoteCreate

FieldTypeNotes
customer_id *string
sell *Money
buy_currency *stringenum: USDT

Quote

FieldTypeNotes
id *string
customer_id *string
sell *Money
buy *Money
rate *stringString decimal
expires_at *string
status *stringenum: locked · consumed · expired

TravelRuleBeneficiary

Travel Rule data required before release approval (AUSTRAC, in force 2026-07-01, no de-minimis). Field-level source: research §14. Ownership model pending Q23.

FieldTypeNotes
full_name *string
wallet_address *string
wallet_typestringenum: custodial_vasp · self_hosted
vasp_namestring
countrystring

OrderCreate

FieldTypeNotes
quote_id *string
beneficiary *TravelRuleBeneficiary
external_refstring

Order

FieldTypeNotes
id *string
quote_id *string
customer_id *string
deposit_idstring
status *stringenum: awaiting_funds · funds_received · awaiting_manual_release · released · settled · suspended_name_mismatch · blocked_tr_incomplete · funding_reversed · cancelled
receipt_idstring
created_at *string

DepositStatus

receivedmatchedpostedsuspended_name_mismatchreturnedreversed

Deposit

FieldTypeNotes
id *string
va_id *string
customer_idstring
amount *Money
payer_name *string
name_matchstringenum: pending · matched · mismatch
status *DepositStatus
received_at *string

Receipt

FieldTypeNotes
id *string
order_id *string
initial_amount *Money
feesobject[]
final_amount *Money
rate *string
destination_tx_hashstring
content_hash *stringHash over canonical receipt JSON; verify via GET /receipts/{id}/verify.
signaturestringDetached signature — GA with U1.3/T46.
pdf_urlstring
issued_at *string

WebhookEventType

customer.kyc.updatedva.assigneddeposit.receiveddeposit.matcheddeposit.suspendeddeposit.reversedquote.expiredorder.state.changedorder.releasedorder.settledreceipt.issued

WebhookEndpoint

FieldTypeNotes
id *string
url *string
events *WebhookEventType[]
status *stringenum: active · disabled
secretstringReturned once at creation; HMAC-SHA256 event signing.

WebhookEnvelope

Delivery envelope for all events. Signed; retried with backoff; delivery log queryable.

FieldTypeNotes
id *string
type *WebhookEventType
created_at *string
data *object