Register the backend client with the FHIR authorization server, providing the client's public JWKS endpoint or static public key so the server can verify assertions.
Build a signed JWT client assertion: set iss and sub to the client_id, aud to the token endpoint URL, include a short exp (≤5 minutes), and a unique jti; sign with the client's private key.
POST to the token endpoint with form-encoded body: grant_type=client_credentials, client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer, client_assertion=<signed JWT>, and scope listing the required SMART scopes.
Parse the JSON response to extract the access_token and expires_in; store the token securely for reuse within its lifetime.
Attach the access token to FHIR API requests as a Bearer token in the Authorization header.
Implement token refresh logic: when the token is near expiry, repeat the client assertion build and token request steps rather than caching long-lived credentials.
Known gotchas
The grant_type must always be client_credentials — never put the jwt-bearer URN in the grant_type field; the jwt-bearer URN belongs exclusively in client_assertion_type.
The client_assertion JWT must use a unique jti on every request; reusing a jti will cause the authorization server to reject the request as a replay attack.
The aud claim in the client assertion must exactly match the token endpoint URL as registered with the authorization server — a mismatch is a common cause of authentication failure.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp