Troubleshooting
Authentication failures
Every way a request gets rejected before it reaches your data, and how to tell them apart.
Authentication problems produce three different codes, and they mean genuinely different things. Read the code, not the status.
| Code | Status | What it actually means |
|---|---|---|
UNAUTHORIZED | 401 | The key was missing, malformed, or is not a key we recognize |
VALIDATION_ERROR | 400 | An organization key was used without X-Tenant-Id |
FORBIDDEN | 403 | The key is valid, but not for this tenant |
401 UNAUTHORIZED#
Check the scheme first#
The header takes the ApiKey scheme — not Bearer, and not the bare key. This is the single most common cause.
curl https://core-api.heysadie.ai/assistants \
-H "Authorization: ApiKey YOUR_API_KEY"-H "Authorization: Bearer YOUR_API_KEY" # wrong scheme
-H "Authorization: YOUR_API_KEY" # no scheme
-H "X-Api-Key: YOUR_API_KEY" # wrong headerThen check for invisible damage#
A key that looks right can still be wrong. In order of likelihood:
- Trailing newline.
API_KEY=$(cat key.txt)keeps the newline;$(cat key.txt | tr -d '\n')does not. - Shell interpolation. Single quotes do not expand
$VARS.-H 'Authorization: ApiKey $KEY'sends the literal$KEY. - A rotated key. Rotation invalidates the previous key immediately. If it stopped working rather than never working, this is why.
- The wrong secret entirely. The client server secret on the API Keys page verifies webhooks. It is not an API key and will never authenticate a request.
printf '%s' "$ONCORE_API_KEY" | wc -c # length, without a trailing newline
printf '%s' "$ONCORE_API_KEY" | tail -c 4 # last characters400 VALIDATION_ERROR on an organization key#
Organization keys work across every tenant in the organization, so they cannot infer which tenant you mean. Every tenant-scoped request needs the header:
curl https://core-api.heysadie.ai/assistants \
-H "Authorization: ApiKey ORG_API_KEY" \
-H "X-Tenant-Id: 0195f1e2-1111-7000-8000-000000000000"The only endpoints that accept an organization key without X-Tenant-Id are the org-level audits: POST /v1/retention/audits and POST /v1/churn/audits.
A tenant key does the opposite — it already knows its tenant, so sending X-Tenant-Id is unnecessary.
403 FORBIDDEN#
The key authenticated, but the tenant you named does not belong to its organization. Usually one of:
- A tenant ID copied from a different organization
- A tenant key being used with another tenant's
X-Tenant-Id - A tenant that has since been moved or removed
Confirm the tenant in your dashboard before assuming the key is at fault.
404 on a resource you can see in the dashboard#
Not an auth failure, but it presents as one. RESOURCE_NOT_FOUND is returned both when a resource does not exist and when it belongs to another tenant — deliberately, so the API does not confirm the existence of other tenants' data.
If a GET /assistants/{id} 404s on an assistant you are looking at in the dashboard, you are almost certainly authenticated as the wrong tenant.
Still stuck#
Reduce to the smallest possible request. If this works, the problem is in your client; if it does not, the problem is the key.
curl -i https://core-api.heysadie.ai/assistants \
-H "Authorization: ApiKey YOUR_API_KEY"-i prints the status line and headers, so you can see the code rather than guessing from an empty body.
Related#
- Authentication — key types and headers.
- Errors — the full error envelope.