Skip to main content

Authentication & API Access

This integration crosses three separate identity boundaries: you (the Funding Party), your disbursement agent, and the pool-gate eligibility service. Each boundary has its own credential. None of them are interchangeable, and the pool-gate in particular never sees your identity at all, only a machine credential. This page is the single reference for every credential you'll encounter across Getting Started, Eligibility, and Disbursement.

Credentials at a glance

CredentialFormatGatesSent as
Funding Party API keylgk_live_..., capability-scopedYour disbursement agent's /api/disburse, /api/validate, or (for holder.* capabilities) the transfer/send roles in Account OperationsAuthorization: Bearer
SIWX sessionSession cookie/api/employers/onboard, /api/employers/eligibility/resync, /api/employers/holder/onboard, /api/employers/keysCookie: sessionId=...
Pool-gate OAuth (read)OAuth 2.0 client-credentials, scope pool:readPool-gate whitelist/blacklist readsAuthorization: Bearer
Pool-gate OAuth (write)OAuth 2.0 client-credentials, scope admin:whitelist:writePool-gate whitelist writes (platform-internal)Authorization: Bearer
Pool-gate admin keyStatic keyFallback for pool-gate whitelist writes when OAuth isn't configuredX-API-Key
Agent loopback tokenStatic bearer you setFences the agent's local API from other processes on its hostAuthorization: Bearer
Agent-to-platform edge tokenPer-tenant bearerThe agent's outbound connection to the platformAuthorization: Bearer

Funding Party API key

The credential your disbursement agent uses to authorize requests. Format: the literal prefix lgk_live_ followed by 40 base64url characters. Every key carries exactly one capability, and can only reach the routes that capability covers:

CapabilityGrants
disburse/api/disburse, /api/validate on your own agent (the Disbursement flow).
holder.readReading your own pool subject's notes: /api/balance and the balance role. No ability to move funds.
holder.transferThe transfer role.
holder.sendThe send/withdraw role.
roster.attestAttaching recipients' W and registering their P — the attest role. Decides who may be paid, not who is paid.

A key that can disburse cannot also transfer or send, and vice versa: this is enforced platform-side, not by convention, specifically because disburse's worst case (paying a whitelisted recipient) and transfer/send's worst case (moving or paying out the holder's whole balance) are different enough that a shared credential would silently widen whichever role holds it.

roster.attest is separated for the same reason in the other direction: fused with disburse, anything holding your payroll credential could add a wallet to the eligibility set. And holder.read is separated in a third direction — a holder.transfer key can already read your notes, so permitting it as a read credential would work, and would mean no deployment can be read-only. A reporting job should hold something that genuinely cannot move value.

Obtaining one. Minted at POST /api/employers/keys, SIWX-session-gated, body { "capability": "...", "name": "..." }. The plaintext is shown exactly once, in that response; only a hash is persisted server-side. Unlike account registration, minting is additive: it doesn't revoke any other live key on your wallet, so you hold one key per capability you actually use (up to 50 live keys per wallet). See Account Operations → Minting a scoped credential for a full example.

Rotation. There's no dedicated rotate call: mint a new key with POST /api/employers/keys, switch your agent over to it, then revoke the old one with DELETE /api/employers/keys/:id (its id comes back from the mint response, or from GET /api/employers/keys, which lists every key you've ever minted). Revocation takes effect on the agent's next request, no redeploy needed.

Sending it.

Authorization: Bearer lgk_live_...

against your own disbursement agent's /api/disburse or /api/validate. The agent validates it by forwarding to the platform's POST /api/employers/verify-key; if that verify call can't be reached, the agent fails closed (401) rather than accepting an unverifiable key.

Treat it like a production secret

Anyone holding this key can trigger disbursements against your funder wallet, gated only by whatever allowance and balance that wallet holds. Store it in a secrets manager, not in source control or agent config files checked into version control.

SIWX session

"Sign-in with X": a wallet-signature login, distinct from every credential above. It authenticates a human driving admin actions, never a disbursement call. It's required for:

  • POST /api/employers/onboard
  • POST /api/employers/eligibility/resync
  • POST /api/employees/update-encryption-key

The session is a cookie (sessionId), backed by a server-side row with a default 24-hour TTL. Onboarding and eligibility-resync are further gated by an allowlist of wallet addresses configured for your deployment. An unconfigured allowlist closes these routes entirely; only wallets on it can call them.

Pool-gate OAuth

The pool-gate never receives your SIWX identity or your Funding Party API key; it only ever authenticates a machine principal, via OAuth 2.0 client-credentials (Cognito). There are two scopes:

ScopePurpose
pool:readReading whitelist entries, blacklist non-membership intervals, and the pool-gate's public signing key.
admin:whitelist:writeWriting new whitelist entries. Platform-internal: issued to the platform's own service credential, not to callers directly.

A token is minted by POSTing client id/secret/scope to the configured token endpoint; scopes are namespaced (resourceserver/scope; a bare pool:read is rejected). If OAuth isn't configured for a deployment, whitelist writes fall back to a static X-API-Key admin credential instead.

How your agent gets a read token. Two options:

  1. Mint it yourself: configure the agent with the OAuth client-credentials directly, and it requests its own pool:read token.
  2. Have the platform vend one: call the platform's /agent-edge/bootstrap, which returns a short-lived pool:read token scoped to your deployment. Preferred: your agent never needs to hold the raw OAuth client secret at all.

Agent loopback token

A bearer secret that fences your disbursement agent's local HTTP API off from other processes on the same host, unrelated to any Funding Party identity or to the pool-gate. Use this instead of (or alongside) Funding Party API key auth if the agent's /api/disburse needs to accept calls from a co-located scheduler that shouldn't need to hold your production lgk_live_... key.

If neither this nor Funding Party key verification is configured, the agent auto-generates an ephemeral token at boot and logs it. Fine for local testing, not for anything handling real funds.

Agent-to-platform edge token

A per-tenant bearer credential for the agent's own outbound, agent-initiated connection to the platform's /agent-edge. This is what lets the platform recognize which deployment's agent is submitting proved batches for settlement; it's provisioned alongside your deployment, separately from your Funding Party API key.


Trust boundary

SIWX identity is never forwarded to the pool-gate. The pool-gate only ever sees a service credential: either the platform's own (for the SIWX-driven onboarding/resync paths) or your agent's own pool-gate credential (for the direct read path the agent uses before proving). In the direct-agent model there is no SIWX involved on the pool-gate side at all; the agent is a service principal end-to-end, and the read credential lives in your infrastructure, not the platform's.