Skip to content

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.

CodeStatusWhat it actually means
UNAUTHORIZED401The key was missing, malformed, or is not a key we recognize
VALIDATION_ERROR400An organization key was used without X-Tenant-Id
FORBIDDEN403The 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.

Correct
curl https://core-api.heysadie.ai/assistants \
  -H "Authorization: ApiKey YOUR_API_KEY"
All rejected
-H "Authorization: Bearer YOUR_API_KEY"     # wrong scheme
-H "Authorization: YOUR_API_KEY"            # no scheme
-H "X-Api-Key: YOUR_API_KEY"                # wrong header

Then 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.
Check what you are actually sending
printf '%s' "$ONCORE_API_KEY" | wc -c   # length, without a trailing newline
printf '%s' "$ONCORE_API_KEY" | tail -c 4   # last characters

400 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:

Terminal
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.

Minimal reproduction
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.