Interpose

Developer Documentation

Introduction

Interpose is an API-first financial infrastructure platform. Each of the four pillars exposes a REST API (OpenAPI 3.1) and a real-time WebSocket stream (CloudEvents 1.0 over Kafka). Use any pillar independently — there's no forced bundling.

Authentication

All APIs accept two authentication schemes. Use Bearer tokens for portal and client apps; use HMAC signing for server-to-server integrations.

Bearer token (OAuth 2.0 JWT)

http
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

HMAC-SHA256 (server-to-server)

Include three headers on every request. Requests older than 30 seconds are rejected.

http
X-VM-Key-Id:    your-key-id
X-VM-Timestamp: 1715441400000          # Unix milliseconds
X-VM-Signature: hex(HMAC-SHA256(secret, canonical_string))

Canonical string format:

text
{METHOD}\n{PATH}\n{TIMESTAMP_MS}\n{SHA256_HEX(body)}
python
import hashlib, hmac, time

def sign(secret: str, method: str, path: str, body: bytes = b"") -> dict:
    ts = str(int(time.time() * 1000))
    body_hash = hashlib.sha256(body).hexdigest()
    message = f"{method}\n{path}\n{ts}\n{body_hash}".encode()
    sig = hmac.new(secret.encode(), message, hashlib.sha256).hexdigest()
    return {"X-VM-Key-Id": KEY_ID, "X-VM-Timestamp": ts, "X-VM-Signature": sig}

Event Streams

Every state change in Interpose emits a CloudEvents 1.0 envelope on Apache Kafka. Subscribe via the WebSocket stream endpoint on each API, or consume directly from Kafka.

CloudEvents envelope

json
{
  "specversion":       "1.0",
  "id":                "evt_01HV4Y2K3M5N8P9QR2ST4UVWXY",
  "source":            "com.interpose.baas",
  "type":              "com.interpose.baas.order.filled",
  "datacontenttype":   "application/json",
  "time":              "2026-05-12T14:23:00.000000000Z",
  "data": { ... }
}

Kafka topic registry

TopicPublished byConsumed by
vm.baas.orders.submittedBaaSPost-Trade
vm.baas.orders.filledBaaSPM
vm.baas.orders.cancelledBaaS
vm.baas.positions.updatedBaaSPM
vm.post-trade.transactions.initiatedPost-Trade
vm.post-trade.transactions.settledPost-TradeBaaS
vm.post-trade.transactions.failedPost-TradeBaaS
vm.pm.rebalancing.initiatedPM
vm.pm.rebalancing.completedPM
vm.pm.rebalancing.orders.createdPMBaaS

Errors

All errors return a JSON body with a detail field. Compliance rejections include a failed_checks array.

StatusMeaning
400Bad request — malformed JSON or missing required field
401Unauthenticated — invalid or expired token / HMAC signature
403Forbidden — valid credentials but insufficient scope
404Resource not found
409Conflict — e.g. cancelling an already-filled order
422Validation error or compliance rejection
429Rate limited — retry after the Retry-After header
5xxServer error — contact api@interposehq.com

IDs, Types & Precision

All entity IDs are ULIDs — lexicographically sortable and safe to embed in URLs.

PrefixEntityExample
usr_Userusr_01HV4Y2K3M5N8P9QR2ST4UVWXY
acct_Accountacct_01HV4Y2K3M5N8P9QR2ST4UVWXY
ord_Orderord_01HV4Y2K3M5N8P9QR2ST4UVWXY
txn_Transactiontxn_01HV4Y2K3M5N8P9QR2ST4UVWXY
ptf_Portfolioptf_01HV4Y2K3M5N8P9QR2ST4UVWXY
reb_Rebalancing runreb_01HV4Y2K3M5N8P9QR2ST4UVWXY
stl_Settlement (internal)stl_01HV4Y2K3M5N8P9QR2ST4UVWXY

Financial precision rules

All monetary and quantity values are returned as strings, never floats. Floating-point precision errors in financial calculations are a regulatory liability.

Data typeJSON typePrecisionExample
Fiat monetary amountstring4 decimal places"152.3400"
Share quantitystring8 decimal places"10.00000000"
Crypto (BTC)string8 decimal places"0.00150000"
FX ratestring6 decimal places"1.265432"
Performance returnstring10 decimal places (stored)"0.0452318920"
TimestampstringISO 8601 nanoseconds UTC"2026-05-12T14:23:00.000000000Z"