External API overview
The Auth API endpoints external applications use for SSO, token verification, company directory lookups, category lookups, and application-access checks.
Base URL
Local development default:
http://localhost:8081
All application endpoints are versioned under /api/v1.
Security model for external apps
External apps integrate against an application record, not a company. Each application owns:
- a unique
appId— a human-readable identifier, carried informationally in JWT claims; - one or more access keys — named RSA key pairs created on the support
console's Access keys page. Each key belongs to exactly one application
and carries its own Allowed URLs list (validates
redirect_uriandpost_logout_redirect_uri), an optional activity window (startsAt/expiresAt), and a status (ACTIVE/REVOKED).
The access key's public key is the client credential: it identifies the
calling app during OAuth and external API calls and verifies the JWTs the app
receives. The private key stays server-side, encrypted, and never leaves the
Auth service. A key is usable when it is ACTIVE, inside its activity
window, and its application is ACTIVE. An application can hold many keys at
once, so rotation is zero-downtime: create a replacement key, reconfigure the
client, then revoke the old key.
The access key public key identifies the calling app, but it is not a secret. It is accepted only together with a valid app-signed user JWT or the OAuth flow proof (authorization code + PKCE verifier, or a current refresh token).
For company directory and access-control endpoints under
/api/v1/external/**, send both:
Authorization: Bearer <app-signed-user-access-token>
X-App-Public-Key: -----BEGIN PUBLIC KEY-----\nMIIB...\n-----END PUBLIC KEY-----
Rules enforced by the API:
- The public key must belong to a usable access key of an active application.
- The bearer token must be an app-signed
accessJWT (not an internal UI token). - The token signature must verify with the access key that signed it (resolved
from the JWT header
kid), and that key must be a usable key of the same application — so tokens survive key rotation but never cross applications. - The token's
application_idclaim must match the application resolved fromX-App-Public-Key. - The authenticated user must still be active.
- The user must have an active membership in the company carried in the
token's
company_idclaim, and that company must be subscribed to the application.
For headers, send the PEM with escaped newlines (\n) or send the base64
public-key body. The access key private key never leaves the Auth service
and is never available to embed anywhere.
Pagination and search
Paged endpoints use Spring pageable query parameters:
| Parameter | Example | Notes |
|---|---|---|
page | 0 | Zero-based page number. |
size | 50 | Page size. |
sort | name,asc | Can be repeated for multiple sorts. |
search | finance | Supported on company users, categories, and applications. |
Paged responses follow the standard Spring Page shape:
{
"content": [],
"pageable": {},
"totalElements": 0,
"totalPages": 0,
"size": 50,
"number": 0
}
Public auth endpoints
These endpoints do not require an Authorization header. They are used only by
the Authfy UI and never produce application JWTs:
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/v1/auth/login | Authenticate a user; returns internal Authfy UI tokens (HMAC-signed). |
POST | /api/v1/auth/refresh | Rotate the internal UI refresh token. |
POST | /api/v1/auth/introspect | Validate an application JWT. Requires X-App-Public-Key or appPublicKey in the body. |
External apps must use the OAuth/OIDC flow — not
/api/v1/auth/login — to obtain tokens.
Introspect an application JWT
POST /api/v1/auth/introspect
Content-Type: application/json
X-App-Public-Key: -----BEGIN PUBLIC KEY-----\nMIIB...\n-----END PUBLIC KEY-----
{
"token": "eyJhbGciOiJSUzI1NiJ9..."
}
Active response:
{
"active": true,
"subject": "user-uuid",
"tokenType": "access",
"claims": {
"sub": "user-uuid",
"email": "member@example.com",
"company_id": "company-uuid",
"company_slug": "company-slug",
"application_id": "application-uuid",
"app_id": "hrm",
"public_key_fingerprint": "sha256-fingerprint",
"token_type": "access"
}
}
Operational endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET | /health | Health check. |
GET | /info | Application info. |
GET | /actuator/health | Spring actuator health check. |
GET | /actuator/info | Spring actuator info. |
GET | /swagger-ui/** | Swagger UI where enabled. |
GET | /v3/api-docs/** | OpenAPI JSON where enabled. |
Endpoints not intended for external apps
/api/v1/admin/** endpoints are reserved for Authfy administrators. External
applications should use /api/v1/oauth/**, /api/v1/external/**, and
/api/v1/me/apps instead.
In this section
- OAuth 2.0 / OIDC — the SSO flow and token endpoints.
- Directory endpoints — company, users, categories, applications, current-user apps.
- Management API — access-key authenticated company provisioning and user management.
- JWT verification — verifying Authfy JWTs in Node, Spring, and PHP.