Skip to main content

Authentication

The Batch API uses OAuth 2.0 client credentials. Exchange your client credentials for an access token, then send the token on every request.

Authorization: Bearer eyJ...

There are no API keys and no refresh tokens. Request a new token when the current one expires.

Get a Token​

curl -s -u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=batches:write batches:read" \
https://api.amorphous.health/oauth/token

Send the client ID and secret with HTTP Basic authentication (client_secret_basic). The body is application/x-www-form-urlencoded.

ParameterRequiredDescription
grant_typeYesclient_credentials
scopeNoSpace-delimited scopes. Defaults to every scope on the client
client_assertion_typePrivate key JWT onlyurn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertionPrivate key JWT onlySigned JWT. See Private Key JWT
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "batches:write batches:read"
}
FieldDescription
access_tokenSend as Authorization: Bearer
token_typeAlways Bearer
expires_inSeconds until expiry. 900 by default, configurable from 300 to 3600 per client
scopeScopes granted

Cache the token and request a new one about 60 seconds before it expires. The token endpoint allows 30 requests per minute per client.

Scopes​

ScopeGrants
batches:writeCreate, add, upload, submit, cancel, and delete
batches:readBatches, documents, entities, results, and document Bundles
system/*.rs or system/*.readEvery /fhir/R4 read (SMART v2 or v1)
system/{Type}.rs or system/{Type}.readRead and search one resource type, such as system/Condition.rs

Batch routes do not accept SMART scopes, and /fhir/R4 does not accept batches:read. Patient/{ID}/$everything returns every type, so it needs system/*.rs or system/*.read.

Private Key JWT​

Use private_key_jwt instead of a shared secret. Register a public key with Amorphous, as an inline JWKS or an HTTPS jwks_uri, then sign an assertion for each token request.

curl -s -X POST https://api.amorphous.health/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "scope=batches:write batches:read" \
-d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
-d "client_assertion=$ASSERTION"
ClaimValue
iss, subYour client ID
audhttps://api.amorphous.health/oauth/token
expNo more than 5 minutes after iat
jtiUnique per assertion. A reused jti is rejected

Supported algorithms are RS256, RS384, ES256, and ES384. SMART Backend Services clients should use RS384 or ES384.

Access Token Claims​

Access tokens are JWTs signed by https://api.amorphous.health. You do not need to read them, but the claims are stable.

ClaimDescription
subYour client ID
organization_idYour organization. Requests never take an organization parameter
modetest or live
scopeScopes granted
expExpiry time

Rotate Credentials​

A client secret is shown once, when it is created. Store it in a secret manager. Amorphous keeps only a keyed hash and cannot recover it.

  1. Ask for a second secret, or publish a new key in your JWKS.
  2. Deploy the new credential.
  3. Revoke the old secret once traffic has moved.

A client can have two active secrets. Disabling a client takes effect immediately, including for tokens already issued.

Discovery​

DocumentPath
Authorization server metadataGET /.well-known/oauth-authorization-server
Signing keysGET /.well-known/jwks.json
SMART configurationGET /fhir/R4/.well-known/smart-configuration