Skip to content

Errors & authentication

This page covers structured API errors, correlation ids, and how customers authenticate to Exhale APIs. Webhook ingest uses per-source verification — HMAC for PagerDuty and manual webhooks; URL/header tokens for most other sources. See the integrations index and guides linked below.

Full route catalog: API reference.


Structured errors

Non-success responses use a consistent JSON shape:

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Pulse … not found",
    "correlation_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}
FieldDescription
codeMachine-readable error code (e.g. NOT_FOUND, VALIDATION_ERROR, UNAUTHORIZED)
messageHuman-readable detail
correlation_idRequest id for support and log lookup

Every response includes an X-Correlation-Id header. Clients may send their own value; otherwise the API generates a UUID. Match this id in support requests.

HTTPTypical codeWhen
400BAD_REQUESTMissing required webhook fields, invalid Content-Length
401UNAUTHORIZEDBad or missing signature / session
403FORBIDDENViewer role, disabled tenant, expired trial
404NOT_FOUNDUnknown pulse, unmapped PagerDuty account, unknown webhook token
409CONFLICTConflicting state (e.g. retry-triage race, billing conflict)
413PAYLOAD_TOO_LARGEBody over size limit (default 1 MiB)
422VALIDATION_ERRORSchema validation failure
429RATE_LIMITEDPer-IP webhook or API rate limit (Retry-After)
503(varies)Redis fail-closed, maintenance, ambiguous account mapping
500INTERNAL_ERRORUnexpected server error

Customer authentication

Customer UI and /auth routes use the exhale_session HTTP-only cookie after login or signup.

Mutating /auth routes require:

  • Valid session
  • X-CSRF-Token header matching the CSRF cookie (double-submit pattern)

In staging and production, mutating routes also require Origin or Referer from an allowed browser UI origin.

MFA (TOTP): Paid tenant admins may be required to enroll in TOTP before full session access when admin MFA is required. Trial signups and optional member/viewer MFA policies are configured under Settings → Account → Sign-in & MFA.

Integration setup routes (PUT /auth/integrations/*, manual webhook connect, etc.) use session + CSRF. See OpenAPI security schemes SessionCookie and CsrfHeader.

API key bridge (operations)

When the platform operator configures API_KEY and PULSES_API_KEY_BRIDGE_ENABLED=true, requests may authenticate with:

X-API-Key: <platform-api-key>

This scopes GET /pulses and related ops-bridge routes to the dev tenant only — not arbitrary tenant data. The bridge is off by default in staging and production; production customer access uses sessions or tenant API keys.

OpenAPI scheme: ApiKeyAuth.

Tenant API keys (customer)

Tenant admins issue keys under Settings → Security & data → API keys (GET/POST /auth/api-keys, revoke). Secrets are shown once (exh_… prefix); only a hash is stored.

X-API-Key: exh_<secret>

Scopes: read for list/get; admin also allows retry-triage and archive. Keys are tenant-scoped (not the platform bridge).


Webhook authentication

Webhooks do not use session cookies. Each source has its own verification:

Auth styleSourcesHow
HMAC signaturePagerDuty, Manual webhookHMAC-SHA256 of the raw body as v1=<hex> (X-PagerDuty-Signature or X-Exhale-Signature). Manual also requires X-Exhale-Webhook-Token (header route) or a path token.
URL / header tokenOpsGenie, Splunk On-Call, Grafana, Datadog, Alertmanager, New Relic, Sentry, Honeycomb, Elastic, Dynatrace, AWS CloudWatchOpaque tenant token via header X-Exhale-Webhook-Token (preferred) or POST /webhooks/{source}/{token}. No vendor HMAC.

OpenAPI schemes: PagerDutySignature, ExhaleSignature, ExhaleWebhookToken.


Pulses API (tenant-scoped)

GET /pulses, GET /pulses/{id}, timeline/notes routes, and POST /pulses/{id}/retry-triage require:

  1. Valid exhale_session cookie, or
  2. Tenant API key (X-API-Key starting with exh_), or
  3. Platform X-API-Key when the pulses bridge is enabled (dev-tenant only)

Mutations that change tenant data from the browser (archive, notes, feedback) also require X-CSRF-Token. Retry-triage with a tenant API key requires admin scope.

Cross-tenant pulse ids return 404. Retry with a session requires member or admin role; viewers receive 403.

List responses include X-Total-Count for pagination.


Health

EndpointPurpose
GET /healthDatabase, Redis, triage queue depth — healthy or degraded (always 200)
GET /health/liveProcess liveness for load balancers (no dependency checks)

Neither endpoint requires authentication.


Published OpenAPI policy

Live Swagger UI (/docs), ReDoc (/redoc), and /openapi.json are disabled on staging and production API hosts. Only local development / test expose those explorers on the API.

Use this documentation site’s API reference for the published (integrator-filtered) OpenAPI schema.


Exhale by Kolstrom Systems LLC