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.
| .00 | happy path — matched → posted → order releasable → receipt issued |
| .13 | payer name mismatch — deposit suspended_name_mismatch, manual-review queue |
| .31 | deposit later reversed — funding_reversed cascades to order/release locks |
| .77 | TR 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.
customers — verify — customer identity, KYC lifecycle (Sumsub-backed)
/customersCreate 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.
- Request
- CustomerCreate
/customers/{customerId}/kyc-sessionStart 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-accounts — settle — named AUD collection accounts (BSB + account + PayID)
/virtual-accountsIssue 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)
/virtual-accounts/{vaId}Fetch a virtual account
- Response
- VirtualAccount· errors: Problem (RFC 7807)
quotes — quote — locked pricing with expiry
/quotesLock a conversion quote (AUD → USDT)
Locked rate with `expires_at`. Consuming an expired quote fails.
- Request
- QuoteCreate
orders — settle — quote consumption through to gated release
/ordersCreate 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`).
- Request
- OrderCreate
deposits — settle — AUD receipts, name-matching states (read-only)
receipts — attest — verifiable transaction attestations
/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).
/receipts/{receiptId}/verifypublic · no authVerify a receipt by content hash (PUBLIC — no auth)
- Response
- object· errors: Problem (RFC 7807)
webhooks — event subscriptions and delivery
/webhook-endpointsList webhook endpoints (with delivery log pointers)
- Response
- object· errors: Problem (RFC 7807)
/webhook-endpointsRegister a webhook endpoint
- Request
- object
- Response
- WebhookEndpoint· errors: Problem (RFC 7807)
Schemas
Problem
RFC 7807. Compliance blocks carry a machine-readable `compliance_reason`.
| Field | Type | Notes |
|---|---|---|
| type * | string | |
| title * | string | |
| status * | integer | |
| detail | string | |
| compliance_reason | string | enum: blocked_kyc_incomplete · blocked_kyc_evidence_missing · blocked_tr_incomplete · suspended_name_mismatch · trading_frozen_by_recon · funding_reversed |
Money
| Field | Type | Notes |
|---|---|---|
| currency * | string | enum: AUD · USDT |
| minor * | integer | Integer minor units. AUD: e4. USDT: e6. Never floats. |
| decimal * | string | String decimal mirror for display. |
CustomerCreate
| Field | Type | Notes |
|---|---|---|
| type * | string | enum: individual · company |
| legal_name * | string | VA will be issued in this verified name. |
| string | ||
| external_ref | string | Partner-side customer reference. |
Customer
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| kyc_status * | string | enum: none · pending · approved · rejected · frozen |
| kyc_evidence_source | string | Only webhook/api-verified evidence unlocks money actions (ADR-16). |
| created_at * | string |
KycSession
| Field | Type | Notes |
|---|---|---|
| session_id * | string | |
| verification_url * | string | |
| sdk_token | string | |
| expires_at * | string |
VirtualAccount
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| customer_id * | string | |
| account_name * | string | Customer's verified legal name — name-match enforced. |
| bsb * | string | |
| account_number * | string | |
| payid | string | |
| status * | string | enum: active · inactive |
QuoteCreate
| Field | Type | Notes |
|---|---|---|
| customer_id * | string | |
| sell * | Money | |
| buy_currency * | string | enum: USDT |
Quote
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.
| Field | Type | Notes |
|---|---|---|
| full_name * | string | |
| wallet_address * | string | |
| wallet_type | string | enum: custodial_vasp · self_hosted |
| vasp_name | string | |
| country | string |
OrderCreate
| Field | Type | Notes |
|---|---|---|
| quote_id * | string | |
| beneficiary * | TravelRuleBeneficiary | |
| external_ref | string |
Order
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| quote_id * | string | |
| customer_id * | string | |
| deposit_id | string | |
| status * | string | enum: awaiting_funds · funds_received · awaiting_manual_release · released · settled · suspended_name_mismatch · blocked_tr_incomplete · funding_reversed · cancelled |
| receipt_id | string | |
| created_at * | string |
DepositStatus
receivedmatchedpostedsuspended_name_mismatchreturnedreversed
Deposit
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| va_id * | string | |
| customer_id | string | |
| amount * | Money | |
| payer_name * | string | |
| name_match | string | enum: pending · matched · mismatch |
| status * | DepositStatus | |
| received_at * | string |
Receipt
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| order_id * | string | |
| initial_amount * | Money | |
| fees | object[] | |
| final_amount * | Money | |
| rate * | string | |
| destination_tx_hash | string | |
| content_hash * | string | Hash over canonical receipt JSON; verify via GET /receipts/{id}/verify. |
| signature | string | Detached signature — GA with U1.3/T46. |
| pdf_url | string | |
| issued_at * | string |
WebhookEventType
customer.kyc.updatedva.assigneddeposit.receiveddeposit.matcheddeposit.suspendeddeposit.reversedquote.expiredorder.state.changedorder.releasedorder.settledreceipt.issued
WebhookEndpoint
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| url * | string | |
| events * | WebhookEventType[] | |
| status * | string | enum: active · disabled |
| secret | string | Returned once at creation; HMAC-SHA256 event signing. |
WebhookEnvelope
Delivery envelope for all events. Signed; retried with backoff; delivery log queryable.
| Field | Type | Notes |
|---|---|---|
| id * | string | |
| type * | WebhookEventType | |
| created_at * | string | |
| data * | object |