Skip to content

Security & compliance

Organization-level access

Use one organization API key to operate across all your tenants.

The platform hierarchy is organization → tenants → assistants. If you run many tenants (e.g. you're a reseller with one tenant per end-business), an organization API key lets a single integration act on all of them, with no per-tenant key management.

See Authentication for where keys come from and the header format.

How org keys work#

An organization key is accepted on all tenant-scoped routes, but every such request must say which tenant it targets via the X-Tenant-Id header:

Terminal
curl https://core-api.heysadie.ai/assistants \
  -H "Authorization: ApiKey ORG_API_KEY" \
  -H "X-Tenant-Id: 0195f1e2-1111-7000-8000-000000000000"

The request then behaves exactly as if it had been made with that tenant's own key: same endpoints, same payloads, same responses.

FailureResponse
X-Tenant-Id missing on a tenant-scoped route400 VALIDATION_ERROR
The tenant does not belong to your organization403 FORBIDDEN
Bad or unknown key401 UNAUTHORIZED

Organization-level endpoints#

These endpoints take an organization key without X-Tenant-Id, because they act on the organization itself:

EndpointPurpose
POST /v1/retention/auditsFile a data-retention audit
POST /v1/churn/auditsFile a churned-customer cleanup audit
/turn-flags, /transcriber-banks, /full-call-runs and GET /organization/tenantsTranscriber testing, across every tenant of the organization
GET /transcribers and GET /transcribers/{id}Read the transcriber catalogue, which is the same for every tenant

The audits and transcriber testing reject tenant keys. Transcriber testing also rejects an organization key sent with the X-Tenant-Id of one of its tenants, answering 403 ORG_SCOPE_REQUIRED, because its flags, banks and runs belong to the organization, not to one tenant. The catalogue reads accept every kind of key.

Multi-tenant integration patterns#

One backend, many tenants. Keep the org key server-side and inject X-Tenant-Id per request based on which of your customers the request concerns:

Tenant-scoped client
function sadieClient(tenantId: string) {
  const headers = {
    Authorization: `ApiKey ${process.env.SADIE_ORG_API_KEY}`,
    "X-Tenant-Id": tenantId,
    "Content-Type": "application/json",
  };
  return {
    get: (path: string) =>
      fetch(`https://core-api.heysadie.ai${path}`, { headers }).then((r) => r.json()),
  };
}

const { data } = await sadieClient(customer.sadieTenantId).get("/assistants");

Fan-out jobs. For nightly syncs or reporting, iterate your tenant ids and repeat the same call per tenant. The org key spares you a credential per tenant. There is no cross-tenant "list everything" endpoint; reads are always scoped to one tenant at a time.

Provisioning flows. Tenant-scoped provisioning APIs (like WhatsApp onboarding) accept the org key + X-Tenant-Id combination too, so a reseller can onboard any of its tenants from one integration.

An organization key is strictly more powerful than any tenant key: a leak exposes every tenant in the org. Keep it server-side only, and prefer tenant keys for integrations that only ever touch one tenant.

Next steps#