Authentication
Keys, environments, and what never goes in a browser.
Every call carries a secret key as a bearer token.
curl https://api.experthire.cloud/v1/usage \
-H "Authorization: Bearer ehs_sk_test_..."
{
"object": "usage",
"environment": "sandbox",
"livemode": false,
"credits_available": null
}
Getting a key
Settings → Developers in your Expert Hire dashboard. An owner or admin can create one. You see the secret once: it is stored as a one-way digest, so nobody, including us, can retrieve it afterwards.
Two environments
| Prefix | Environment | livemode |
|---|---|---|
ehs_sk_test_ | Sandbox | false |
ehs_sk_live_ | Live | true |
The prefix is the environment. There is no separate parameter and no way for a live key
to act on sandbox data, or the reverse: a sandbox key asking for a live assessment gets
404, not 403, because the object is not in its world at all.
The prefix says test and the environment field says sandbox. They mean the same
thing. Branch on the livemode boolean, which is unambiguous and present on every
object.
credits_available is null in sandbox and on unlimited plans. Sandbox work never
touches your credit balance, so there is nothing to report.
Which credential does what
Three credential types reach this API, and they are not interchangeable.
| Credential | Where it lives | What it can do |
|---|---|---|
ehs_sk_* secret key | Your server | Everything |
| Session JWT | A browser you host | Read and act on the one assessment it was minted for |
ehs_lt_ launch token | A single-use URL | Exchange itself for a session, once |
A session cannot create assessments or read your other candidates. That narrowing is the point: it is what makes it safe to put in a page.
Never in a browser
A secret key acts on the whole organisation. It belongs on your server only.
To put an assessment in a page you host, allowlist the origin with POST /v1/domains and
mint a short-lived session with POST /v1/sessions. The browser holds the session token,
never the key.
Rotating
Create the replacement first, deploy it, then revoke the old key. Revoking accepts a grace window of up to seven days, so the old key keeps working while a rollout finishes rather than failing the moment you click revoke.
Keys do not expire on their own. A key stays valid until you revoke it.
When a call is rejected
| Code | Usually means |
|---|---|
missing_api_key | No Authorization header, or not Bearer <key> |
invalid_api_key | Typo, truncation, or a key from another organisation |
revoked_api_key | Revoked, or its grace window has passed |
secret_key_required | A session token on an endpoint that needs the secret key |
All four are 401. Branch on code, never on the message.
A truncated key is the most common cause of invalid_api_key. Secret keys are long,
and a shell that wraps them or a form field that trims them produces a key that looks
right and is not.
An ehp_ key belongs to the Preparation API and will not
authenticate here. The prefixes are namespaced so a misconfigured integration fails
loudly rather than scoring the wrong thing.
Next
- Environments — what sandbox does and does not do
- Embedding — sessions, for a page you host