Skip to main content

API Keys

Every HANA integration uses API keys scoped to your organization and environment. Keys follow a predictable format so you can identify them quickly in logs:
hana_sk_live_...   → Production key
hana_sk_test_...   → Sandbox key
Never embed API keys in client-side code, mobile apps, or version control. Use environment variables or a secrets manager.

Key Permissions

Keys are scoped to one of three permission levels:
ScopeCan DoUse Case
full_accessAll operationsServer-to-server integrations
engagements_onlyCreate/read engagements, receive webhooksLimited integrations
read_onlyRead engagements, patients, metricsDashboards, reporting

Creating Keys

Keys are provisioned during partner onboarding. To manage keys:
# List active keys
GET /v1/auth/keys

# Rotate a key (old key remains valid for 24 hours)
POST /v1/auth/keys/{key_id}/rotate
Response:
{
  "id": "key_xyz789",
  "prefix": "hana_sk_live_",
  "scope": "full_access",
  "created_at": "2026-02-07T14:30:00Z",
  "expires_at": null,
  "last_used_at": "2026-02-07T14:28:00Z"
}

Key Rotation

HANA supports zero-downtime key rotation. When you rotate a key:
  1. A new key is issued immediately
  2. The old key continues working for 24 hours
  3. After 24 hours, the old key is automatically revoked
This gives your team time to update all services without disruption.

Request Authentication

Include your API key in the Authorization header on every request:
curl -X POST https://api.hana.health/v1/engagements \
  -H "Authorization: Bearer hana_sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{ ... }'
import { HanaClient } from '@hana-health/sdk';

const hana = new HanaClient({
  apiKey: process.env.HANA_API_KEY,
  environment: 'production',
  region: 'eu'
});

// SDK handles authentication automatically
const engagement = await hana.engagements.create({ ... });

Webhook Verification

All outbound webhooks from HANA are signed with HMAC-SHA256 using your webhook secret. Always verify the signature before processing events.

Verification Flow

  1. HANA computes HMAC-SHA256(webhook_secret, raw_request_body)
  2. The signature is sent in the X-Hana-Signature header
  3. Your server recomputes the HMAC and compares
const crypto = require('crypto');

function verifyHanaWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(`sha256=${expected}`),
    Buffer.from(signature)
  );
}

// Express middleware
app.post('/webhooks/hana', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-hana-signature'];
  if (!verifyHanaWebhook(req.body, sig, process.env.HANA_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(req.body);
  // Process event...
  res.status(200).send('ok');
});
Always use timing-safe comparison functions to prevent timing attacks. Never use == for signature comparison.

Organization & Environment Isolation

Each organization gets fully isolated environments:
Organization: "Acme Health"
├── Production
│   ├── API Key: hana_sk_live_...
│   ├── Webhook Secret: whsec_live_...
│   └── Data: Production patients & engagements
└── Sandbox
    ├── API Key: hana_sk_test_...
    ├── Webhook Secret: whsec_test_...
    └── Data: Test patients only (no real calls)
Data never crosses environment boundaries. Sandbox keys cannot access production data.

IP Allowlisting (Optional)

For organizations with strict network policies, restrict API access to specific IP ranges:
POST /v1/auth/ip-allowlist
{
  "allowed_cidrs": [
    "203.0.113.0/24",
    "198.51.100.0/24"
  ]
}
When enabled, requests from non-allowlisted IPs receive 403 Forbidden.

Next: Webhooks

Detailed guide to receiving and processing HANA events.