WalletD developers
API reference

API reference

Three contracts, every operation, and the conventions that hold across all of them.

WalletD publishes three OpenAPI contracts. Two of them are yours to call; the third is the ledger underneath, documented because a partner running the stack has to operate it.

Conventions

These hold for the wallet and auth APIs without exception. The ledger API is a separate service with its own credential; its differences are called out on Reaching the ledger.

Base URLYour deployment's API host, for example https://apigw.walletd.io. The published contracts carry that host as a placeholder; substitute yours
AuthAuthorization: Bearer <credential> on everything except GET /healthz. See Authentication
AmountsInteger minor units. 2500 is $25.00, and there are no floats in either direction
IdsUUIDv7, so they sort by creation time
Money-moving POSTsRequire an Idempotency-Key header. See Idempotency
ErrorsRFC 7807 application/problem+json. Branch on the stable code, never on title or detail. See Errors
PagingCursor-based: ?limit= and ?cursor=, newest first
Rate limits429 rate_limited and 503 bulkhead_full come from the API gateway, not from the service. Both carry the same problem shape; 429 carries Retry-After

An object that exists but belongs to another tenant returns 404, not 403. That is deliberate: an id you do not own has to be indistinguishable from an id that does not exist, or the API becomes a way to enumerate other people's data.

There is no "try it" console

Deliberately. On an API whose calls move real balances, a button that fires a live request from a documentation page is a way to make a mistake, not a convenience. Every operation below shows the request in six languages and the response it returns, and none of them sends anything.

The consequence worth knowing about: this site makes no third-party requests at all. No playground client, no hosted search, no analytics, no fonts from a CDN. It renders on a laptop with no internet, and you can verify that from the artefact rather than taking our word for it.

To actually run a call, use a sandbox key against your own deployment. See Testing and sandbox.

Machine-readable contracts

DocumentURL
Wallet API/openapi.yaml
Auth API/openapi/authsvc.yaml
Ledger API/openapi/ledgerd.yaml
Postman / Bruno collection (wallet)/openapi/walletd.postman.json

These are the contracts the services generate their own server stubs from, copied verbatim. The only things added on the way here are the servers entry (a contract declares a relative URL because it is served from its own host), display names for the tags, the hand-written code samples, and the two problem codes the gateway emits on a service's behalf.

The collection imports into Postman and Bruno. It carries one request per operation with the example bodies from the contract, and two collection variables, baseUrl and apiKey.

Generate a client

Generate one rather than hand-writing it; the contract is the thing that gets CI-gated, not your wrapper.

# Go — types and a client, from the published document
oapi-codegen -generate types,client -package walletd openapi.yaml > walletd.gen.go

# Python, TypeScript, PHP, Java and the rest
npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g python -o ./walletd-python

Both wallet and auth documents are OpenAPI 3.0.3 and declare bearerAuth as the global security scheme, so a generated client picks up the header for you.

A generated client gets you types and transport. It does not get you Idempotency-Key on the money paths, problem-code handling, or Retry-After backoff — those are yours to add, and the Go SDK has them already.

Reading an operation page

Each operation has its own page, grouped by tag. A page shows the path and method, the authentication it requires, its parameters, the request body schema with an example, and every documented response including the problem codes it can return.

The ten money-moving operations additionally carry hand-written samples in curl, Go, Python, PHP, JavaScript and Java — the same six languages, in the same order, as the guides. Those samples are written by hand and reviewed; everywhere else the page shows generated snippets, which are fine for a plain GET and should be read as illustrations rather than as tested code.

On this page