Troubleshooting & FAQ
Last updated: 2026-02-18
Organized by symptom — find your error, understand the cause, apply the fix.
Authentication Errors
I get 401 INVALID_API_KEY
Cause: The API key value is wrong, malformed, or does not exist.
Fix:
- Verify the key starts with
mt_live_and is the full 64-character hex value - Check you haven't accidentally truncated or added whitespace
- Confirm the key was created for this environment (staging vs. production)
- Check the header name is exactly
x-api-key(lowercase, with hyphen)
# Correct
-H "x-api-key: mt_live_a1b2c3d4..."
# Wrong: capital X, missing hyphen, wrong header name
-H "X-API-KEY: mt_live_a1b2c3d4..."
-H "Authorization: Bearer mt_live_a1b2c3d4..."
I get 401 API_KEY_REVOKED or API_KEY_EXPIRED
Cause: The key was revoked by an admin or has passed its expiration date.
Fix:
- Log in to the employer dashboard → API Keys
- Check the key status — if revoked or expired, create a new one
- Update your secret manager with the new
rawKey
I get 403 INSUFFICIENT_SCOPE
Cause: Your API key does not have the scope(s) required by the endpoint.
Fix:
- Check which scope is required — the error response tells you:
{
"code": "INSUFFICIENT_SCOPE",
"requiredScopes": ["fhir:read"],
"keyScopes": ["cohort:read"]
}
- Create a new key with the needed scopes, or ask your admin to update the existing key
Common scope mappings:
| Endpoint pattern | Required scope |
|---|---|
/api/fhir/* (GET) | fhir:read |
/api/fhir/* (POST) | fhir:write |
/api/employer/webhooks/* | webhook:manage |
/api/employer/export/* | export:read or export:create |
/api/employer/sso | sso:manage |
/api/employer/upload-cohort | cohort:write |
I get 403 API_KEY_IP_NOT_ALLOWED
Cause: Your request came from an IP address outside the key's CIDR allowlist.
Fix:
- Check your key's
allowedIpCidrsconfiguration - Find your server's outbound IP:
curl ifconfig.me - Add the IP/CIDR to the key's allowlist, or create a new key without IP restrictions for testing
I get 429 RATE_LIMITED
Cause: Too many requests in the rate-limit window.
Fix:
- Check the
retry-afterheader for how long to wait - Implement exponential backoff in your client
- Batch requests where possible (e.g., use FHIR
_countparameter for larger page sizes) - API key rate limit: 120 requests/minute (default)
- FHIR SMART rate limit: 120 requests/minute per employer
API Version Errors
I get 400 UNSUPPORTED_API_VERSION
Cause: Missing or unrecognized x-api-version header.
Fix:
- Add the header:
x-api-version: 2026-02-01 - Check the error response for the list of supported versions
- The
v1alias also works:x-api-version: v1
# Correct
-H "x-api-version: 2026-02-01"
# Also works
-H "x-api-version: v1"
Webhook Issues
My webhook endpoint never receives events
Checklist:
- Is the subscription active?
GET /api/employer/webhooks/<id>— checkstatus: "active" - Does the URL point to a publicly reachable HTTPS endpoint?
- Did you test with the test endpoint?
POST /api/employer/webhooks/<id>/test - Is your server responding with
2xxstatus within 10 seconds? - Check firewall rules — Bounded Health needs outbound HTTPS access to your URL
Webhook signature verification fails
Most common causes:
- Parsing before verifying: You must verify the raw bytes, not parsed JSON
// WRONG — body is already parsed
app.post("/webhook", express.json(), (req, res) => {
const body = JSON.stringify(req.body); // Re-serialization changes bytes!
verify(body, signature, secret); // Will fail
});
// CORRECT — use raw body
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const rawBody = req.body.toString("utf8"); // Original bytes preserved
verify(rawBody, signature, secret); // Will pass
});
- Wrong secret: Using the API key instead of the webhook signing secret
- Encoding mismatch: The signature header is
sha256=<hex>— make sure you compare the full string including thesha256=prefix
Webhook subscription was auto-disabled
Cause: Too many consecutive delivery failures (default threshold: 10).
Fix:
- Check delivery logs:
GET /api/employer/webhooks/<id>— look atfailureCount - Fix the underlying issue (usually your endpoint is down or returning errors)
- Re-activate:
PATCH /api/employer/webhooks/<id>with{ "status": "active" } - Send a test to verify:
POST /api/employer/webhooks/<id>/test
FHIR Errors
I get a 400 OperationOutcome with invalid
Cause: Invalid resource type, search parameter, or payload format.
Fix:
- Check supported resource types:
Patient,CarePlan,Observation,DiagnosticReport,MedicationRequest - Verify search parameter names match the documented params (e.g.,
patient=Patient/<id>, notpatientId=<id>) - For POST operations, ensure the body includes
resourceTypeand required fields
I get 404 OperationOutcome with not-found
Cause: The patient/resource does not exist in your employer tenant.
Fix:
- Verify the patient ID is correct — use
GET /api/fhir/Patient?_count=5to list available patients - IDs are scoped to your employer tenant — you cannot access other tenants' resources
I get 409 OperationOutcome with duplicate
Cause: Trying to create a FHIR Patient with an email that already exists in your tenant.
Fix:
- Search first:
GET /api/fhir/Patient?email=<email> - If the patient exists, use the existing resource instead of creating a new one
Bulk export is stuck in "pending" or "running"
Cause: The background worker is processing the export. Large cohorts may take several minutes.
Fix:
- Poll the status endpoint:
GET /api/fhir/bulk-export/<exportId> - The response includes progress information
- If stuck beyond 30 minutes, contact support — the worker may be restarting
SCIM Errors
I get 401 from SCIM endpoints
Cause: Missing or invalid bearer token.
Fix:
- Use the SCIM token, not the API key:
Authorization: Bearer <scim_token> - The token was shown once when SCIM was enabled — if lost, rotate it:
curl -X POST "$MT_HOST/api/employer/sso" \
-H "x-api-key: $MT_API_KEY" \
-H "content-type: application/json" \
-d '{ "rotateScimToken": true }'
I get 409 Conflict when provisioning a user
Cause: A user with that email exists in a different employer tenant.
Fix:
- Bounded Health enforces global email uniqueness
- If this user should belong to your tenant, contact support to resolve the conflict
- For testing, use unique email addresses
SCIM user deactivation doesn't remove access
What actually happens:
- User is soft-deactivated (
active: false) - API keys created by the user are revoked
- Active Clerk sessions are revoked (if backend credentials configured)
- The user record remains for audit purposes
If the user can still log in, check that Clerk backend credentials are configured for session revocation.
SDK Issues
SDK type errors after upgrade
Fix:
- Regenerate types from the latest contract:
npm run sdk:ts:generate
npm run sdk:ts:build
- If types still don't match, export and compare contracts:
npm run contracts:export
Still stuck?
- Check the API Key reference for detailed auth requirements
- Check the Webhook reference for delivery and retry details
- Check the FHIR reference for endpoint-specific behavior
- Open your monitoring console at
/employer/integration-monitoringfor real-time telemetry - Contact solutions engineering:
integration@boundedhealth.com