Skip to main content

Troubleshooting & FAQ

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:

  1. Verify the key starts with mt_live_ and is the full 64-character hex value
  2. Check you haven't accidentally truncated or added whitespace
  3. Confirm the key was created for this environment (staging vs. production)
  4. Check the header name is exactly x-api-key (lowercase, with hyphen)
bash
# 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:

  1. Log in to the employer dashboard → API Keys
  2. Check the key status — if revoked or expired, create a new one
  3. 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:

  1. Check which scope is required — the error response tells you:
json
{
  "code": "INSUFFICIENT_SCOPE",
  "requiredScopes": ["fhir:read"],
  "keyScopes": ["cohort:read"]
}
  1. Create a new key with the needed scopes, or ask your admin to update the existing key

Common scope mappings:

Endpoint patternRequired 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/ssosso:manage
/api/employer/upload-cohortcohort:write

I get 403 API_KEY_IP_NOT_ALLOWED

Cause: Your request came from an IP address outside the key's CIDR allowlist.

Fix:

  1. Check your key's allowedIpCidrs configuration
  2. Find your server's outbound IP: curl ifconfig.me
  3. 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:

  1. Check the retry-after header for how long to wait
  2. Implement exponential backoff in your client
  3. Batch requests where possible (e.g., use FHIR _count parameter for larger page sizes)
  4. API key rate limit: 120 requests/minute (default)
  5. 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:

  1. Add the header: x-api-version: 2026-02-01
  2. Check the error response for the list of supported versions
  3. The v1 alias also works: x-api-version: v1
bash
# Correct
-H "x-api-version: 2026-02-01"

# Also works
-H "x-api-version: v1"

Webhook Issues

My webhook endpoint never receives events

Checklist:

  1. Is the subscription active? GET /api/employer/webhooks/<id> — check status: "active"
  2. Does the URL point to a publicly reachable HTTPS endpoint?
  3. Did you test with the test endpoint? POST /api/employer/webhooks/<id>/test
  4. Is your server responding with 2xx status within 10 seconds?
  5. Check firewall rules — Bounded Health needs outbound HTTPS access to your URL

Webhook signature verification fails

Most common causes:

  1. Parsing before verifying: You must verify the raw bytes, not parsed JSON
typescript
// 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
});
  1. Wrong secret: Using the API key instead of the webhook signing secret
  2. Encoding mismatch: The signature header is sha256=<hex> — make sure you compare the full string including the sha256= prefix

Webhook subscription was auto-disabled

Cause: Too many consecutive delivery failures (default threshold: 10).

Fix:

  1. Check delivery logs: GET /api/employer/webhooks/<id> — look at failureCount
  2. Fix the underlying issue (usually your endpoint is down or returning errors)
  3. Re-activate: PATCH /api/employer/webhooks/<id> with { "status": "active" }
  4. 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:

  1. Check supported resource types: Patient, CarePlan, Observation, DiagnosticReport, MedicationRequest
  2. Verify search parameter names match the documented params (e.g., patient=Patient/<id>, not patientId=<id>)
  3. For POST operations, ensure the body includes resourceType and required fields

I get 404 OperationOutcome with not-found

Cause: The patient/resource does not exist in your employer tenant.

Fix:

  1. Verify the patient ID is correct — use GET /api/fhir/Patient?_count=5 to list available patients
  2. 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:

  1. Search first: GET /api/fhir/Patient?email=<email>
  2. 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:

  1. Poll the status endpoint: GET /api/fhir/bulk-export/<exportId>
  2. The response includes progress information
  3. 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:

  1. Use the SCIM token, not the API key: Authorization: Bearer <scim_token>
  2. The token was shown once when SCIM was enabled — if lost, rotate it:
bash
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:

  1. Bounded Health enforces global email uniqueness
  2. If this user should belong to your tenant, contact support to resolve the conflict
  3. For testing, use unique email addresses

SCIM user deactivation doesn't remove access

What actually happens:

  1. User is soft-deactivated (active: false)
  2. API keys created by the user are revoked
  3. Active Clerk sessions are revoked (if backend credentials configured)
  4. 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:

  1. Regenerate types from the latest contract:
bash
npm run sdk:ts:generate
npm run sdk:ts:build
  1. If types still don't match, export and compare contracts:
bash
npm run contracts:export

Still stuck?

  1. Check the API Key reference for detailed auth requirements
  2. Check the Webhook reference for delivery and retry details
  3. Check the FHIR reference for endpoint-specific behavior
  4. Open your monitoring console at /employer/integration-monitoring for real-time telemetry
  5. Contact solutions engineering: integration@boundedhealth.com