Docs
Developers
How to authenticate users, call product APIs, and register your own app on the Spexx core.
Spexx is built as a single identity core with separate product services around it. Every product trusts the same core for sign-in and tokens, so a user logs in once and your service can verify who they are without holding their password. This page covers the four pieces you will touch when you build on Spexx.
On this page
- Spexx ID — sign-in with OIDC.
- The product SDK — login, scoped API calls, branch context.
- Registering a product — getting your OIDC client.
- Service-to-service — client credentials and scopes.
- Webhooks — planned.
Spexx ID (OIDC)
Spexx ID is the identity core. It speaks OpenID Connect, so most OIDC libraries work without a custom integration. User sign-in uses the authorization-code flow with PKCE — your app never sees the password, and the code exchange is bound to a one-time verifier so an intercepted code is useless on its own.
Tokens are signed with RS256. To trust a token, verify its signature against the core JWKS at https://api.spexx.in/.well-known/jwks.json. Fetch the key set once, cache it, and refresh when you see a key id you do not recognize. Never accept a token that is unsigned or that uses a symmetric algorithm.
When you verify a token, check the standard claims: the issuer (iss) is the Spexx core, the audience (aud) is your client, the token has not expired (exp), and the scopes (scope) cover what the request is doing. The subject (sub) is the stable user id.
The product SDK
Each product ships a small SDK so you do not hand-roll the OIDC and token plumbing. It handles three jobs:
- Login. Starts the authorization-code with PKCE flow, completes the redirect, and stores the session. Your app calls one method and gets back a signed session.
- Scoped API calls. Attaches the access token to outgoing requests and refreshes it before it expires. Calls that need a scope the user does not hold are rejected by the service, not silently widened.
- Branch context. A user can belong to a business with several branches, and access is scoped per branch. The SDK carries the active branch on each request so the service returns only that branch's data. Switching branch changes the context for subsequent calls.
Registering a product
A product is an app that trusts Spexx ID. A super-admin registers it in the Spexx admin console. Registration creates the OIDC client your app needs:
- A web OIDC client. Used for user sign-in. You provide the redirect URIs you will use; the core will only return users to a URI on that list. This client is public and relies on PKCE rather than a secret.
- An optional server client. If your service needs to call other services on its own behalf, the super-admin can also issue a confidential client with aclient_id and client_secret for the client credentials flow.
Keep the server secret out of client code and out of source control. If a secret leaks, ask a super-admin to rotate it; the old secret stops working immediately.
Service-to-service
When one service needs to call another with no user present — a background job, a sync, a webhook handler — use the client credentials flow. The service exchanges its client_id and client_secret for an access token, then presents that token to the target service.
These tokens are scoped. A service is granted only the scopes its work requires, so a token issued for one task cannot reach unrelated data. The receiving service verifies the token against the same JWKS and checks that the requested operation is inside the token's scopes. Request the narrowest scope set that gets the job done.
Webhooks
Outbound webhooks are planned. The intent is signed event delivery so your service can react to changes — a new user, a branch added, a payment recorded — without polling. Payloads will be signed so you can verify they came from Spexx, with redelivery on failure. This section will be updated when the API is available.