How the API protects itself
- The engine listens on a loopback address only, and refuses to start on any other. Whatever fronts the API, such as a reverse proxy that terminates TLS, runs on the same host.
- The API is closed by default: a route with no entry in the access table is refused, and the engine checks the table against the routes it serves when it starts.
- The API takes bearer tokens only, checked on every request against your identity provider’s keys. See Identity provider.
- The engine lets an investor’s token read and act for its own holder only, whatever the front end asks.
- A body over the limit, 1 MiB by default and 5 MiB for a statement, is refused 413 before it is read. A field the route does not take is refused 400
unknown-field. - Every write is an operation, and writes are idempotent: the same
Idempotency-Keyand body answers the same operation, so a retry never writes twice. The same key with another body is refused 422idempotency-key-reused. - Every refusal is an RFC 9457 problem document naming the field or the rule that refused, and leaks nothing else: it never repeats the caller’s text, an exception’s text or a token.
- Text bound for the ledger (a settlement id, a label, a reason or a reference) keeps to a fixed shape, checked before anything is stored or submitted.
- The engine’s scheduler and its automatic booking act under subjects of their own, which no token can carry.
- Each webhook delivery carries an HMAC-SHA256 signature over its timestamp and body. See Monitoring.

