Authentication
The Evenhand REST API uses bearer tokens. Send the token in the Authorization header on every request.
Authorization: Bearer evhk_live_<32hex>
Tokens authenticate a brokerage, not a user. The set of resources the token can see, and the operations it can perform, are determined entirely by the token — not by the URL, not by anything in the request body.
Token format
Tokens have a fixed shape:
| Pattern | Environment | Notes |
|---|---|---|
evhk_live_<32hex> | Production | Operates on real brokerage data. Subject to per-key rate limits. |
evhk_test_<32hex> | Test | Operates on the brokerage's test data. Same shape, separate rate pool. |
The trailing 32 hex characters are random. Treat the entire string as opaque — its layout may be extended in future, and parsing it is not part of the contract.
Issuance
Keys are issued from the brokerage settings UI by an admin. The flow is:
- An admin opens Settings → API keys in the web app.
- The admin chooses a name, a scope set, and an optional rate-limit ceiling for the key.
- The platform generates the token and shows the raw value exactly once in the creation dialog.
- After the dialog is closed only the SHA-256 digest of the token is retained. The platform cannot show the raw value again.
If the raw value is lost, revoke the key and issue a new one.
Storage
- At rest. The platform stores only
sha256(token). The raw token is never persisted. - In transit. Always over HTTPS. The API rejects plain-HTTP requests.
- In your code. Store the token in an environment variable or a secret manager. Do not commit it. Do not log it. Do not paste it into bug reports or screenshots.
Revocation
An admin can revoke a key from the same settings page. Revocation is immediate: the next request bearing the revoked token returns 401 invalid_token. There is no grace window.
A revoked token cannot be reactivated. Issue a new one and update the consumer's secret.
Scopes
Every key carries an explicit scope set chosen at issuance. A request that targets an endpoint outside the token's scopes returns 403 insufficient_scope. The error body names the missing scope so the operator knows what to enable on the key.
| Scope | Gates |
|---|---|
contacts:read | Reading contacts. |
contacts:write | Creating, updating, and deleting contacts. |
deals:read | Reading deals and their associated state (offers, exclusivity, lifecycle). |
deals:write | Creating and updating deals; advancing deal state. |
offers:read | Reading offers and the seller-side comparison view as far as the brokerage sees. |
offers:write | Submitting and amending offers on behalf of the brokerage. |
diligence:read | Reading the diligence framework: checklists, uploaded artifacts, analysis output. |
The endpoint catalog in the API reference lists the required scope on each operation. New scopes may be added when new resources are introduced; existing scopes will not be renamed or repurposed within v1.
What the API does not do
- No user-on-behalf-of impersonation. A key cannot be downscoped at request time, and there is no per-request user identity. If you need user-attributed actions, use the web app.
- No OAuth flows. There is no third-party authorization grant in
v1. Keys are issued and held by the brokerage itself. - No public client credentials. Keys are server-to-server. Do not embed them in browser, mobile, or desktop client bundles.