API Reference
OpenAPI 3.1 spec + @hundi/api-client SDK
The OpenAPI 3.1 specification at /openapi.json is the source of truth for the Hundi gateway. The TypeScript SDK @hundi/api-client is the reference implementation — every customer-facing endpoint is wrapped with typed methods, idempotency keys, and optional HMAC signing.
Spec · OpenAPI 3.1
api.hundi.network/openapi.json
Machine-readable. Generate clients in any language via openapi-generator-cli, oapi-codegen, or equivalent. Schema includes 25 endpoints across quotes, transactions, principals (Trust Registry V1), agents (Mode B), ISO 20022 ingress + egress, and audit log proofs.
Browse interactively at /docs (Swagger UI).
SDK · TypeScript
@hundi/api-client
Reference implementation. HundiClient wraps fetch with typed methods, generates idempotency keys (UUIDv4) on POST, and signs HMAC-protected mutations when credentials are supplied. Errors raise HundiApiError with the parsed { ok: false, code, message } envelope plus status code.
Node 18+. ESM. Apache-2.0. Source mirrors the OpenAPI 3.1 contract — bytes-for-bytes compatible with any other generated client.
Install
The SDK is published to npm as @hundi/api-client. For air-gapped or offline institutional environments, a versioned tarball is available at the stable URL below.
# npm / pnpm / yarn — preferred
npm add @hundi/api-client
pnpm add @hundi/api-client
yarn add @hundi/api-client
# Versioned tarball — air-gapped fallback
curl -sLO https://docs.hundi.network/sdk/hundi-api-client-0.1.0.tgz
pnpm add ./hundi-api-client-0.1.0.tgz
# Codegen from OpenAPI spec — any language
npx @openapitools/openapi-generator-cli generate \
-i https://api.hundi.network/openapi.json \
-g python \
-o ./hundi-clientCurrent version: 0.1.0. Direct download: hundi-api-client-0.1.0.tgz (18 KB, includes dist/ + .d.ts + sourcemaps).
Quickstart — TS
Read-only flows (quotes, transactions, audit proofs) work without credentials. Mutating routes require HMAC signing when the gateway is in HMAC_ENFORCEMENT_MODE=required; in optional mode they accept either signed or unsigned requests, and in off mode HMAC is ignored. Production runs required.
Construct the client
import { HundiClient, HundiApiError } from '@hundi/api-client';
// Unauthenticated — reads only
const client = new HundiClient({
baseUrl: 'https://api.hundi.network',
});
// Authenticated — HMAC-signs mutating routes
const authedClient = new HundiClient({
baseUrl: 'https://api.hundi.network',
credentials: {
apiKey: process.env.HUNDI_API_KEY!,
secret: process.env.HUNDI_API_SECRET!,
},
});Create a quote + accept
const { quote, risk } = await client.createQuote({
pair: { base: 'USD', quote: 'INR' },
side: 'buy',
notional_base: '10000.00',
principal_did: 'did:hundi:0xabc...',
beneficiary_did: 'did:hundi:0xbenef...',
});
// The risk envelope carries the parallel-gate decision (sanctions, KYC,
// limits, agent_scope, velocity). A denial returns 403 with risk.decision
// = 'rejected' and full per-check detail.
if (risk.decision === 'rejected') {
console.error('Quote rejected:', risk.reasons);
} else {
const { transaction } = await authedClient.acceptQuote(quote.id, {
principal_did: 'did:hundi:0xabc...',
beneficiary_did: 'did:hundi:0xbenef...',
});
console.log('Transaction id:', transaction.id);
}Poll transaction status + audit chain
const tx = await client.getTransaction(transactionId);
// tx.status: 'pending' | 'submitting' | 'submitted' |
// 'finalized' | 'failed' | 'blocked' | 'cancelled'
const auditResponse = await client.getTransactionAudit(transactionId);
// auditResponse.events: ordered audit_log entries for this transaction —
// includes IVMS101 packet, sanctions screening result, ZK facts, both
// XRPL hashes (EscrowCreate + EscrowFinish) once finalized.
// For real-time updates instead of polling, subscribe to the WS feed:
// wss://api.hundi.network/v1/stream/events?kinds=transactions.finalized,transactions.blockedRegulator-grade proof for an audit row
const proof = await client.getAuditProof(auditRowId);
// proof: {
// leaf_hash, // sha256(canonical_bytes)
// leaf_index,
// proof: [ // Merkle inclusion path
// { sibling, position: 'left' | 'right' },
// ...
// ],
// root_hash, // daily Merkle root for proof.date
// canonical_bytes, // exact bytes the leaf was hashed from
// xrpl_anchor_tx_hash, // on-chain anchor (mainnet or testnet)
// xrpl_ledger_index,
// anchored_at,
// }
//
// Independent verification: rehash canonical_bytes, walk the proof to
// the root, then fetch the XRPL tx and compare its hundi/audit/root
// memo. The verify-audit CLI in the Hundi repo demonstrates the full
// algorithm in ~50 lines.Quickstart — curl
Any language can integrate via raw HTTP. The endpoints are JSON over HTTPS; mutating routes require an X-Idempotency-Key header (UUIDv4 recommended) and, when HMAC is enforced, the X-Hundi-API-Key / X-Hundi-Timestamp / X-Hundi-Signature triple.
# Public read-only request
curl -s https://api.hundi.network/v1/transactions?limit=10 | jq
# Authenticated request (HMAC enforcement: required)
TS=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
BODY='{"pair":{"base":"USD","quote":"INR"},"side":"buy","notional_base":"10000.00"}'
# Canonical signing input: METHOD\nPATH\nTIMESTAMP\nBODY
INPUT=$(printf 'POST\n/v1/quotes\n%s\n%s' "$TS" "$BODY")
SIG=$(printf '%s' "$INPUT" | openssl dgst -sha256 -hmac "$HUNDI_API_SECRET" -hex | awk '{print $2}')
curl -s -X POST https://api.hundi.network/v1/quotes \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: $(uuidgen)" \
-H "X-Hundi-API-Key: $HUNDI_API_KEY" \
-H "X-Hundi-Timestamp: $TS" \
-H "X-Hundi-Signature: $SIG" \
-d "$BODY"HMAC enforcement
The gateway runs in one of three modes. The active mode is exposed at GET /v1/auth/whoami.
off
No validation
HMAC headers ignored. Test environments only.
optional
Validate when present
Signed requests validated. Unsigned requests accepted. Soft-launch mode for migrating existing institutional clients.
required
Reject unsigned
Every mutation must sign. Revoked keys reject. V1 GA production mode.
Applied to /v1/quotes, /v1/quotes/:id/accept, /v1/principals, /v1/agents and their revocations, /v1/transactions/:id/co-sign, and /v1/iso20022/pain001. Freshness window: ±5 minutes from server clock. Constant-time signature compare.
ISO 20022 (bank-grade ingress + egress)
Tier-1 banks integrate via standard ISO 20022 messages — no custom client required. Inbound: a pain.001 credit transfer initiation triggers the engine quote pipeline; outbound: pacs.002 status, pacs.008 credit transfer, and camt.054 debit/credit notification close the loop.
POST
/v1/iso20022/pain001
Accepts XML credit transfer initiation. Namespace 09/10/11. V1 single-payment (one PmtInf / one CdtTrfTxInf). The Hundi V1 extension lives in RmtInf.Ustrd as HUNDI/PAIR/USD/INR/SIDE/buy. Idempotency keyed on EndToEndId. Returns pacs.002 ACSP with HUNDI_QUOTE_ID in StsRsnInf.AddtlInf.
GET
/v1/iso20022/transactions/:id/pacs008 + /camt054
Pull-based egress for finalized settlements. pacs.008 returns the FIToFICustomerCreditTransfer (XRPL EscrowFinish hash threaded through RmtInf as the cover reference). camt.054 returns the debit notification (BkTxCd PMNT/ICDT/XBCT). Both walk the audit chain to reconstruct the original EndToEndId and IVMS101 packet.
Endpoint reference
The SDK methods map 1:1 onto gateway endpoints. Detail pages document the request / response shape of each.
POST /v1/quotes
client.createQuote()
Request a quote with optional principal + beneficiary DIDs. Returns { quote, risk }.
POST /v1/quotes/:id/accept
client.acceptQuote()
Commit to a quote within its TTL. Triggers atomic XRPL settlement. Returns the transaction handle.
GET /v1/transactions(...)
client.listTransactions(), getTransaction(), getTransactionAudit()
List, read, and inspect the per-transaction audit chain (IVMS101 + sanctions + ZK + both XRPL hashes).
POST /v1/agents(...)
Mode B agent surface
Provision delegated AI-agent DIDs with scoped capability claims. Co-sign holds enforce 5-minute approval windows on agent-initiated settlements.
Real-time events
Instead of polling, subscribe to the WebSocket feed for quote + transaction lifecycle events. Filters by kinds, pair, or principal_did.
// Browser or Node; the SDK does not yet wrap this — use a WS library
import WebSocket from 'ws';
const ws = new WebSocket('wss://api.hundi.network/v1/stream/events');
ws.on('open', () => {
ws.send(JSON.stringify({
type: 'subscribe',
topic: 'events',
kinds: ['transactions.finalized', 'transactions.blocked', 'co_sign.held'],
pair: 'USD/INR',
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data.toString());
if (msg.type === 'event') {
console.log(msg.kind, msg.payload);
}
});
// 30s heartbeat; reply to ping with pong. Reconnect with exponential
// backoff + jitter on connection drop.Error envelope + status codes
Every non-2xx response from the gateway carries a structured error envelope. The SDK raises HundiApiError with status, code, and the parsed envelope.
try {
await authedClient.acceptQuote(quoteId, { principal_did: '...' });
} catch (err) {
if (err instanceof HundiApiError) {
if (err.code === 'RISK_REJECTED') {
// Risk gate denied — see err.envelope for per-check detail
} else if (err.code === 'KYC_REFRESH_OVERDUE') {
// Principal's annual KYC refresh is past due; settlement-time block
} else if (err.code === 'AGENT_NOT_AUTHORISED') {
// Mode B: (agent_did, pair) not in the agent's scope
} else {
// err.status, err.code, err.envelope, err.bodyText all available
}
}
}Spec, SDK, and these docs are versioned with the gateway. Drift between the OpenAPI spec at /openapi.json and these pages is a bug — report at platform@hundi.network.