ERIP

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

SurfaceJWTAPI keyNotes
/companies/**, /mcpData 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 - Admin or Member within the tenant - controls who can manage members, service keys, and contact info.
  • The role is emitted as a JWT claim and enforced by the TenantAdmin authorization 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.

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.

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 keysService keys
ListGET /v1/auth/api-keysGET /v1/tenant/api-keys/service
RevokeDELETE /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:

EndpointCredits
GET /companies/search1
GET /companies/{id}/detail50

Credit costs are configurable server-side and reported on every credited response:

X-Credits-Remaining: 95
X-Credits-Cost: 5

When 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.

On this page