Both the GHARRA Registry API and the Nexus A2A protocol use token-based authentication. This guide covers getting credentials, auth flows, required headers, and security best practices.
Symphonix Health exposes two API systems with different auth models. The table below summarises how they compare.
| Aspect | GHARRA Registry | Nexus A2A |
|---|---|---|
| Protocol | REST / HTTP | JSON-RPC 2.0 |
| Auth methods | JWT, mTLS, DPoP | JWT HS256 |
| Config variable | GHARRA_AUTH_MODE | NEXUS_JWT_SECRET |
| Scopes | gharra:read gharra:write gharra:admin | nexus:invoke |
| Dev mode | GHARRA_AUTH_MODE=disabled | Default dev secret |
| Production | JWT or mTLS required | Strong secret required |
The GHARRA zero-trust gateway re-authenticates every request. No implicit trust from network location. Choose the auth method that fits your deployment.
Create an API key via the billing endpoint. The raw key is returned only once — store it securely.
curl -X POST https://registry.symphonix.health/v1/admin/billing/api-keys \ -H "Content-Type: application/json" \ -d '{ "org_id": "my-org", "display_name": "Production Key", "tier": "team", "scopes": ["gharra:read", "gharra:write"] }'
{
"key_id": "gharra_key_01HXR...",
"raw_key": "gharra_sk_live_abc123...",
"org_id": "my-org",
"tier": "team",
"scopes": ["gharra:read", "gharra:write"],
"created_at": "2026-03-29T10:00:00Z"
}
Pass the token in the Authorization header. GHARRA validates tokens against the configured JWKS endpoint.
import httpx headers = {"Authorization": f"Bearer {token}"} resp = httpx.get( "https://registry.symphonix.health/v1/discover", params={"capability": "fhir-r4-patient-search"}, headers=headers, )
Set the JWKS endpoint for token validation:
GHARRA_AUTH_MODE=jwt GHARRA_JWT_JWKS_URI=https://your-idp.example/.well-known/jwks.json
For highest security, use certificate-based authentication. Both client and server present X.509 certificates. Configure with:
GHARRA_AUTH_MODE=mtls
Use the token_binding: mtls_cnf_x5t_s256 parameter in discovery queries to find agents that require mTLS.
DPoP binds access tokens to the cryptographic key held by the client, preventing token replay attacks. Configure with:
GHARRA_AUTH_MODE=dpop
All POST and PUT requests to GHARRA require these headers:
X-Idempotency-KeyUUID format. Required for all mutation endpoints (POST, PUT). Ensures replay safety — if a request is retried with the same key, the original result is returned without re-executing the operation.
If-MatchRequired for PUT (update) operations. Contains the ETag from the previous GET response. Enables optimistic concurrency — updates fail with 412 if the record has been modified since you last read it.
All agents in the Nexus mesh sign their requests with JSON Web Tokens (JWT) using HS256.
| Claim | Type | Description |
|---|---|---|
| sub | string | Agent DID (e.g. did:web:hospital.org:agents:triage) |
| iat | integer | Issued At (Unix timestamp) |
| exp | integer | Expiration (max 1 hour recommended) |
| scope | string | Required: nexus:invoke |
Header: {"alg": "HS256", "typ": "JWT"}
from shared.nexus_common.auth import mint_jwt token = mint_jwt( subject="did:web:hospital.org:agents:triage", secret="your-jwt-secret", ) print(token)
python -c "from shared.nexus_common.auth import mint_jwt; print(mint_jwt('test', 'dev-secret-change-me'))"
curl -X POST http://localhost:8100/rpc/triage_agent \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -H "X-Agent-ID: did:web:hospital.org:agents:triage" \ -d '{"jsonrpc":"2.0","method":"tasks/send","params":{...},"id":1}'
The Clinician Avatar agent exposes a convenience endpoint for browser-safe tokens during local development:
curl http://localhost:8039/dev/token
Development only. The /dev/token endpoint is automatically disabled when a non-default JWT secret is configured. Never rely on it in production.
Optional DID signature verification is controlled by the DID_VERIFY environment variable. Disabled by default for local development.
DID_VERIFY=true
The GHARRA Python SDK handles token management automatically.
from gharra.sdk import GharraClient async with GharraClient( "https://registry.symphonix.health", api_key="gharra_sk_live_abc123...", org_id="my-org", ) as gharra: agents = await gharra.discover("radiology-summarization", jurisdiction="GB")
from gharra.sdk import GharraClient # Works when GHARRA_AUTH_MODE=disabled (default in dev) async with GharraClient("http://localhost:8400", org_id="my-org") as gharra: agents = await gharra.discover("fhir-r4-patient-search")
from gharra.sdk import GharraClient, GharraError async with GharraClient("http://localhost:8400", org_id="my-org") as gharra: try: result = await gharra.invoke(agent_id, payload={...}) except GharraError as e: if e.status == 401: print("Authentication failed — check your API key") elif e.status == 403: print("Insufficient scopes — need gharra:write")
Set expires_at on API keys. For JWTs, use short expiration windows (1 hour max for Nexus). Revoke compromised keys immediately via DELETE /v1/admin/billing/api-keys/{key_id}.
Request only the scopes you need. Use gharra:read for discovery-only integrations. Reserve gharra:write for agent registration, and gharra:admin for billing and computer-use operations.
The GHARRA gateway runs pattern-matching middleware that hard-blocks any inbound payloads containing health data. GHARRA never stores PHI — it is a trust anchor and key directory only. Keep PHI in your clinical systems, not in registry requests.
API keys and JWT secrets must be stored server-side. Use environment variables or a secrets manager. The Nexus /dev/token endpoint is for local development only.
Production checklist: Set GHARRA_AUTH_MODE to jwt or mtls. Change the default NEXUS_JWT_SECRET from dev-secret-change-me. Set GHARRA_ENV=production for strict CORS enforcement. Configure GHARRA_CORS_ORIGINS with your allowed origins.
You have your credentials. Now explore the full API surface.