Authentication
Authenticate Eigenn public API v1 requests with a scoped API key or an OAuth access token.
Summary
Protected Eigenn API operations accept one credential format:
Authorization: Bearer <token>The token can be an Eigenn API key or an OAuth access token. The public contract does not document X-API-Key, query-string credentials, cookies, or basic authentication for protected resource operations.
Capabilities
Use API keys for a server-side integration or OAuth for delegated user access. Machine-to-machine OAuth uses a separate service principal. Each protected operation checks the scopes available to that credential; possession of a token alone does not grant every operation.
Prerequisites
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://api.eigenn.io/v1 |
| Sandbox | https://api-staging.eigenn.io/v1 |
In the current public contract, the sandbox environment runs on the api-staging host. Keep the credentials and the test records separate for each environment.
Concepts
Scope Presets
| Preset | Description |
|---|---|
| apis.all | Expands to every public resource read and write scope. |
| apis.read | Expands to every public resource read scope. |
| Restricted | Stores only the selected resource scopes. |
Each operation documents its required scope. The scope registry includes the following names; a registered scope does not guarantee a matching endpoint or a choice in the settings selector:
| Resource | Read scope | Write scope |
|---|---|---|
| Bank accounts | bank-accounts.read | bank-accounts.write |
| Chat | chat.read | chat.write |
| Customers | customers.read | customers.write |
| Documents | documents.read | documents.write |
| Inbox | inbox.read | inbox.write |
| Invoices | invoices.read | invoices.write |
| Metrics | metrics.read | metrics.write |
| Notifications | notifications.read | notifications.write |
| Reports | reports.read | reports.write |
| Search | search.read | — |
| Tags | tags.read | tags.write |
| Teams | teams.read | teams.write |
| Tracker entries | tracker-entries.read | tracker-entries.write |
| Tracker projects | tracker-projects.read | tracker-projects.write |
| Transactions | transactions.read | transactions.write |
| Users | users.read | users.write |
| Workflows | workflows.read | workflows.write |
| Operations | operations.read | operations.write |
| Runs | runs.read | — |
Read and write scopes are independent: customers.write does not imply customers.read. The settings selector currently offers only one of None, Read, or Write per listed resource. It omits some registered resources, including chat, metrics, workflows, operations, and runs; Reports and Search offer Read only. Do not choose All merely to assume a missing least-privilege combination is supported.
The presets expand at authentication time. All and Read Only can therefore include newly registered scopes; use explicit grants when you need a fixed permission set.
Eigenn rejects credentials with no effective scopes. API keys and user-linked OAuth tokens depend on current team membership. A Viewer retains only read scopes, even if the token originally included writes; a write-only token can become unusable. Machine-to-machine tokens use their active service principal and team instead of a human membership.
Workflow
API Keys
Create keys from Settings → Developer → API keys.
- Select Create API key.
- Enter a name of at least two characters identifying the service and environment. This is a label, not an environment switch.
- Change the default All preset to Restricted for a limited grant, or choose Read Only when all readable resources are appropriate.
- Select the necessary resource scopes.
- Create the key.
- Copy the secret.
- Store the secret in a server-side secret manager.
Only an owner can create, edit, or delete a team API key. Creating or editing requires effective Scale access or higher and billing write access. Scale permits five keys; Enterprise has no key-count limit. The current count check also applies to edits, so editing can be blocked when the limit is reached. Deletion does not require the Scale plan gate.
The full secret appears once. Edit changes the name and scopes without changing the secret or its creator. Rotate by creating a replacement, deploying it, and deleting the old key; reserve capacity for both keys during the transition.
Example:
curl --request GET \
--url https://api.eigenn.io/v1/customers?pageSize=25 \
--header "Authorization: Bearer $EIGENN_API_TOKEN" \
--header "Accept: application/json"This request needs customers.read.
OAuth
The public authorization server supports:
- authorization code
- refresh token
- client credentials
Open Settings → Developer → OAuth apps and select Create OAuth app. Owners and Members can manage team OAuth apps; Viewers can read them but cannot save changes. This differs from owner-only API-key management.
The authorization flow confirms:
- client ID
- exact registered redirect URL
- requested scopes
- selected team membership
- a nonempty S256 PKCE challenge for public clients, with the matching verifier checked at token exchange
- a writable team role before approving write scopes
Authorization and token endpoints:
OAuth-capable clients can use the discovery documents at:
- https://api.eigenn.io/.well-known/oauth-protected-resource
- https://api.eigenn.io/.well-known/oauth-authorization-server
For authorization-code and refresh grants, confidential clients authenticate with client_secret in the request body. Public clients must not send a secret; authorization-code exchange uses the PKCE verifier. Match the registered redirect URI exactly. The authorization state must be 32–512 characters using letters, digits, underscores, periods, or hyphens; generate a random value and validate the returned state.
Refresh rotates the access/refresh pair and revokes the old pair. Store both new tokens together and serialize refresh attempts; a refresh request may narrow its original scopes, not broaden them.
Client credentials requires an active confidential application and an active service principal with registered public keys, a team, and allowed scopes. Authenticate with a signed private_key_jwt assertion, including a fresh jti and the required principal claims. Granted scopes must be allowed by both the app and principal. Tokens expire in 15 minutes and have no refresh token. An application secret alone is insufficient. The discovery document currently lists none and client_secret_post, but omits this private_key_jwt requirement; do not infer machine-to-machine authentication from that list alone.
Send the resulting access token in the Authorization: Bearer header. Never substitute an OAuth application secret for a resource bearer token.
Behavior specification
401 and 403
| Status | Description |
|---|---|
| 401 | The Authorization header is absent, malformed, invalid, expired, or not bound to an accessible team. |
| 403 | Authentication succeeded, but the credential lacks a necessary scope, including scopes removed by its current team role. |
Scope errors can include the necessary scopes and the granted scopes. If the response includes a request ID, log it before you contact support.
Handle Credentials
- Never embed a privileged token in browser or mobile code.
- Do not put a token in a URL.
- Use one credential for each service and each environment.
- To rotate a key, deploy the replacement key before you revoke the old key.
- Delete unused OAuth redirect URLs.
- Revoke access when a vendor or team member no longer needs it.
- Do not use All access when a pair of read and write scopes is enough.
Diagrams
Rendering diagram…
Screenshots
Not applicable: this page describes an API or a non-visual workflow rather than an application screen.
Verification
Confirm a New Credential
For an API key or user-linked OAuth token with users.read, call:
curl --request GET \
--url https://api.eigenn.io/v1/users/me \
--header "Authorization: Bearer $EIGENN_API_TOKEN"A successful response identifies the human user. Also verify a known team-scoped resource and the selected API environment before a write; the profile alone does not prove the intended team. A service-principal token does not represent a human profile, so use an operation allowed for that principal instead of relying on users/me.
- As an eligible owner, create a restricted API key with users.read. Confirm the one-time secret display and that editing scopes does not rotate the secret. For OAuth, obtain the access token through the selected grant rather than treating the app secret as a token.
- Make a GET request to
/users/mewithAuthorization: Bearer <token>. Expected: API returns authenticated user details matching your workspace and environment. - Keep at least one valid scope, remove the scope required by another operation, and confirm 403. Test an empty grant separately: it is rejected at authentication. Change a synthetic user to Viewer and confirm write access is removed.
- Use an expired, malformed, or revoked token and call any operation. Expected: API returns a 401 status indicating invalid or missing authorization.
- Check logs for any request IDs included in scope error responses. Expected: Log entry contains the provided request ID for support reference.