- Public reads for discovery, reputation, public identity, health, version, and docs.
- Agent-signed requests using
X-Leash-Sigfor endpoints scoped to one agent identity. - API keys for legacy authenticated API surfaces such as receipts and payment-link CRUD.
POST /v1/agents/{mint}/api-keys use X-Leash-Sig instead.
Key prefixes pick the network
The first segment of a key encodes the cluster it can act on. The API loads the right RPC, scopes every database query, and rejects any attempt to reach across networks.| Prefix | Network | Use this when… |
|---|---|---|
lsh_test_* | solana-devnet | Building, integration tests, CI, demos. Free RPC, faucet stables. |
lsh_live_* | solana-mainnet | Production. Real money, mainnet RPC, mainnet receipts and explorer. |
lsh_test_* key cannot see a mainnet event, mainnet receipt, or
mainnet agent. A lsh_live_* key cannot see anything from devnet.
Searching a devnet signature with a lsh_live_* key returns 404
even though the signature exists on devnet — this is the explorer’s
isolation guarantee.
Agent-created keys
Agents can create their own API keys without a dashboard or admin secret:owner_wallet= the agent executive public key.agent_mint= the signed agent mint.scopes= exactly["agent"].
prefix, last4, metadata, and timestamps.
UI and admin-issued keys
The web apps can still create user/wallet keys for signed-in users, and platform operators can issue keys through admin routes. Those keys may carry broader surface scopes such asagents, marketplace, or admin. Agent-created keys
are deliberately narrower: they carry only the agent scope and are bound to one
agent mint.
The prefix is purely a routing hint and tells you which cluster the
key acts on at a glance. The opaque tail is high-entropy; treat the
full string as a secret.
Per-request context
Two optional headers (or body fields, where supported) flow into every event row and receipt for traceability:| Field | Where it lives | Purpose |
|---|---|---|
Idempotency-Key | Header, on POST only | Replays the prior response if the same key is reused. See Idempotency. |
X-Leash-Client-Ref | Header, any method | Free-form caller reference. Stored on the event row, returned on lookup, surfaced in the explorer. |
client_reference | Body field on every prepare and submit endpoint | Same as the header. Body wins when both are set. |
Rate limits
Each API key gets a sliding-window quota that resets every minute. The default is generous and split per route family so a noisyPOST /v1/receipts flow can’t starve your prepare traffic.
Headers on every response:
429 with the same headers and a retry_after
field in the JSON body. The limiter is global across the API
fleet — retrying against a different region won’t get you more
budget.
Rotating and revoking
- Rotate — issue a new key, deploy it, then have us revoke the old one. There’s no client-side rotation flow yet.
- Revoke — keys can be flipped to
revoked_at = NOW()at any time. The next call returns401 invalid_api_key. - Audit — every authenticated call writes the (hashed) key id and
client_referenceonto the event row. Deleting a key does not delete its history.
