Authentication
Heads up — this page will change. How you obtain credentials is moving to
console.esus.health, which is currently in development. API key provisioning, team access, and initial login will happen through the console. The API-side verification (JWT onAuthorization: Bearer …, API keys onX-API-Key: …) is not changing, so code you write against the examples below will keep working. We will update this page with the new credential-issuance flow when the console ships.
ESUS supports two authentication methods: JWT Tokens for user sessions and API Keys for machine-to-machine communication.
Method 1: JWT Tokens
JWTs (JSON Web Tokens) are used for user authentication.
Login
curl -X POST https://api.esus.health/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@hospital.com",
"password": "SecurePass123!"
}'
Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": "900s"
}
Using the Access Token
Include the token in the Authorization header:
curl -X GET https://api.esus.health/fhir/Patient \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Renewing the Token
Access tokens expire after 15 minutes (900 seconds). Use the refresh token to obtain a new access token:
curl -X POST https://api.esus.health/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "YOUR_REFRESH_TOKEN"
}'
Method 2: API Keys
API Keys are ideal for server-to-server communication.
Create an API Key
curl -X POST https://api.esus.health/api-keys \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Server",
"scopes": ["Patient.read", "Observation.read", "Observation.write"]
}'
Response (HTTP 201 Created):
{
"id": "c1a2e3d4-5b6f-7890-abcd-ef1234567890",
"name": "Production Server",
"clientId": "a7b1c2d3e4f56789abcdef0123456789",
"secret": "3f8c2a105b4e4d8a9c1f2e7a8b6d4f906fa6c1a2e3d4b5c6",
"scopes": ["Patient.read", "Observation.read", "Observation.write"],
"expiresAt": null,
"active": true,
"rateLimit": null,
"createdAt": "2026-04-21T10:30:00Z"
}
Both clientId and secret are random hex strings (no prefixes). Save secret immediately — it is returned only once and cannot be retrieved again.
Using an API Key
Send the credentials in the X-API-Key header as clientId:secret:
curl -X GET https://api.esus.health/fhir/Patient \
-H "X-API-Key: a7b1c2d3e4f56789abcdef0123456789:3f8c2a105b4e4d8a9c1f2e7a8b6d4f906fa6c1a2e3d4b5c6"
Scope Permissions
Scopes follow the Resource.action pattern:
| Scope | Permission |
|---|---|
| Patient.read | Read Patient resources |
| Patient.write | Create/update/delete Patients |
| Patient.* | All Patient operations |
| *.read | Read all resources |
| * | Full access |
Method 3: SMART on FHIR (OAuth 2.0)
SMART on FHIR is the standard OAuth 2.0 authorization flow for third-party healthcare apps. Use this when building apps that act on behalf of a user.
Discover the Authorization Server
curl https://api.esus.health/.well-known/smart-configuration
Response:
{
"authorization_endpoint": "https://api.esus.health/smart/authorize",
"token_endpoint": "https://api.esus.health/smart/token",
"capabilities": ["launch-ehr", "client-public", "client-confidential-symmetric", "sso-openid-connect"],
"scopes_supported": ["openid", "fhirUser", "patient/*.read", "patient/*.write", "user/*.read", "system/*.read"]
}
Step 1: Register Your Application
curl -X POST https://api.esus.health/smart/apps \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My FHIR App",
"redirectUris": ["https://myapp.com/callback"],
"scopes": ["patient/*.read", "openid", "fhirUser"],
"isConfidential": true
}'
Response:
{
"id": "app-12345",
"clientId": "client-abc",
"clientSecret": "secret-xyz",
"redirectUris": ["https://myapp.com/callback"]
}
Step 2: Authorization Request (PKCE)
Redirect the user’s browser to /smart/authorize (it is a GET endpoint; the user-agent performs the request):
GET https://api.esus.health/smart/authorize
?client_id=client-abc
&response_type=code
&scope=patient/*.read openid fhirUser
&redirect_uri=https://myapp.com/callback
&state=random-state-string
&code_challenge=BASE64URL(SHA256(code_verifier))
&code_challenge_method=S256
Step 3: Token Exchange
curl -X POST https://api.esus.health/smart/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE" \
-d "redirect_uri=https://myapp.com/callback" \
-d "client_id=client-abc" \
-d "client_secret=secret-xyz" \
-d "code_verifier=YOUR_CODE_VERIFIER"
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "patient/*.read openid fhirUser",
"patient": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"fhirUser": "Practitioner/a7b1c2d3-e4f5-6789-abcd-ef0123456789"
}
Step 4: Use the Token
curl https://api.esus.health/fhir/Patient/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
SMART Scopes
| Scope | Access |
|---|---|
patient/*.read | Read all resources for the in-context patient |
patient/*.write | Write resources for the in-context patient |
user/*.read | Read resources accessible to the current user |
system/*.read | System-level read (for backend services) |
openid | OpenID Connect identity token |
fhirUser | Current user FHIR resource reference |
Quick Reference
| Method | When to Use | Header |
|---|---|---|
| JWT | User sessions, internal apps | Authorization: Bearer token |
| API Key | Server to server, CLI tools | X-API-Key: clientId:secret |
| SMART on FHIR | Third-party apps, user-delegated access | Authorization: Bearer oauth_token |
Next Steps
Now that you understand authentication, learn about the most important FHIR resource: Patient.