Authentication
ERIP API authentication - JWT sessions, user and service API keys, the tenant/user model, and the credit system.
Every request carries one of two credentials: a JWT bearer token (for interactive sessions - dashboards, support scripts) or an API key (for programmatic access - data pipelines, MCP clients). The two schemes map to different surfaces on purpose.
Scheme ↔ endpoint matrix
| Surface | JWT | API key | Notes |
|---|---|---|---|
/companies/**, /mcp | ✅ | ✅ | Data plane - automated access is the point |
/auth/** (self-service: /me, /credits, /api-keys) | ✅ | ✅ | Introspection + own key management |
/tenant/** (admin actions: invites, service keys, contact) | ✅ | ❌ | Dashboard-only |
A leaked API key - user key or service key - can burn credits on data endpoints but cannot escalate inside the tenant or provision new users.
The tenant/user model
- Every user belongs to exactly one tenant. Billing, credits, and contact info live on the tenant; members share the same pool.
tenantRole-AdminorMemberwithin the tenant - controls who can manage members, service keys, and contact info.- The role is emitted as a JWT claim and enforced by the
TenantAdminauthorization policy on every/tenant/**endpoint.
See Tenants & Members for the lifecycle.
First-time sign-in
There is no public registration. Every tenant is provisioned by ERIP staff; the first admin of a new tenant receives an invite email.
1. Accept the invite
The invite email contains a one-time link:
GET /v1/auth/accept-invite?token=…Opening it activates the account (sets status to Active, clears the invite token) and emails the user a short-lived magic link.
2. Verify the magic link
The magic link is a GET to /v1/auth/login-link?token=…. Hitting it returns a LoginResponse:
{
"token": "eyJhbGciOiJIUzI1NiIs…",
"expiresAt": "2026-04-22T15:00:00Z",
"user": {
"id": "01968a1c-…",
"name": "Jane Doe",
"email": "jane@acme.test",
"tenantRole": "Admin",
"tenantId": "019db4fc-fdd3-7a6a-927f-dccf298ef5c9"
},
"tenant": {
"id": "019db4fc-fdd3-7a6a-927f-dccf298ef5c9",
"displayName": "Acme Capital Partners",
"tier": "Starter"
}
}Magic links are single-use and expire in 15 minutes.
3. Request another magic link any time
curl -X POST /v1/auth/request-login-link \
-H "Content-Type: application/json" \
-d '{"email": "jane@acme.test"}'Always returns 200 - the server does not leak whether an email is registered.
JWT sessions expire after 60 minutes by default. Re-request a magic link to sign in again.
API keys
API keys are the primary way machines hit ERIP data endpoints. Two flavours:
- User key - owned by a human. Dies when that user is suspended.
- Service key - owned by the tenant itself. Survives user turnover. Typical use: CI, scheduled ingest jobs, internal integrations.
Both are SHA-256 hashed at rest; the raw key is returned once, at creation. Only the first 8 characters (erip_abc1…) are stored alongside for identification.
Create a user key
curl -X POST /v1/auth/api-keys \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d '{"name": "Production"}'Create a service key (tenant admin only)
curl -X POST /v1/tenant/api-keys/service \
-H "Authorization: Bearer TENANT_ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"name": "Daily ingest"}'Use a key
curl /v1/companies/search?name=Siemens \
-H "X-Api-Key: erip_YOUR_KEY"Manage keys
| User keys | Service keys | |
|---|---|---|
| List | GET /v1/auth/api-keys | GET /v1/tenant/api-keys/service |
| Revoke | DELETE /v1/auth/api-keys/{keyId} | DELETE /v1/tenant/api-keys/service/{keyId} |
Revocation is immediate - the next request with the revoked key fails with 401.
Credits
Credits are tenant-scoped. Every member of a tenant draws from the same pool. Each call consumes credits based on the endpoint:
| Endpoint | Credits |
|---|---|
GET /companies/search | 1 |
GET /companies/{id}/detail | 50 |
Credit costs are configurable server-side and reported on every credited response:
X-Credits-Remaining: 95
X-Credits-Cost: 5When the tenant's balance is exhausted the API returns 402 Payment Required.
Check the tenant's balance
curl /v1/tenant/credits \
-H "Authorization: Bearer YOUR_JWT"Attributed history
curl /v1/tenant/credits/history?limit=50 \
-H "Authorization: Bearer YOUR_JWT"Each transaction records the tenant, the user who triggered it (null for service-key calls), the endpoint, and the amount - so tenant admins can see which teammate or integration is consuming the pool.