API keys
Mint, list, and revoke the machine API keys that authenticate every request — nk_live_ and nk_sandbox_, scoped, shown once.
An API key is how your infrastructure authenticates — a secret in a server env var, not a user login. This page covers minting, listing, and revoking keys over the API. For how keys travel on requests and what sandbox vs. live means, see Authentication.
Key prefixes#
Every key is bound to one environment, and you can tell which from its prefix:
| Prefix | Environment | Resolves to |
|---|---|---|
nk_live_… |
Live | Real patients and pharmacies (requires an active agreement). |
nk_sandbox_… |
Sandbox | Synthetic patients + a mock pharmacy. |
Keep every key server-side. Never ship one in a browser, a mobile app, or client-side code.
The secret is shown once#
When you create a key, the plaintext key is returned exactly once, in the create response, and is never retrievable again. neolife stores only a hash. Capture it at creation time and put it straight into your secret store. If you lose it, you revoke the key and mint a new one — there is no "reveal" endpoint.
Create a key#
curl -X POST https://api.neolife.health/v1/developer/keys \
-H "Authorization: Bearer $NEOLIFE_API_KEY" \
-H "Idempotency-Key: 8c2f0a1e-4b7d-4e33-9a6c-2d1f5b8e0c74" \
-H "Content-Type: application/json" \
-d '{
"name": "shopify-fulfillment-worker",
"environment": "sandbox",
"scopes": ["orders:write", "orders:read"]
}'
name— a human label so you can tell keys apart in the list.environment—sandboxorlive. Determines the prefix you get back.scopes— optional. Omit for a full-access key; include one or more scopes to mint a restricted key. A restricted key with an empty scope list is rejected with400.
The response returns the plaintext key alongside the public representation:
{
"key": "nk_sandbox_9f3c1a7e2b8d4056a1c9e7f30d2b6a84",
"apiKey": {
"id": "key_7Qw2eR",
"name": "shopify-fulfillment-worker",
"environment": "sandbox",
"prefix": "nk_sandbox_9f3c1a7e",
"scopes": ["orders:write", "orders:read"],
"createdAt": "2026-07-06T14:12:00Z",
"revokedAt": null
}
}
apiKey.prefix is a non-secret fragment you can safely log or display to identify a key later. The full key is the only field you can't fetch again.
Creating a key is a mutation, so send an Idempotency-Key. A retried create with the same key replays the original response instead of minting a second key.
Scopes#
A key can be full-access or restricted to a set of scopes. Scope your keys to the least privilege the integration needs — a webhook-processing worker that only reads orders doesn't need write access.
| Scope | Grants |
|---|---|
orders:read |
Read orders and their status. |
orders:write |
Create, approve, and submit orders. |
intake:read / intake:write |
Read and manage compliance intake. |
catalog:read |
Read your formulary. |
webhooks:manage |
Manage webhook endpoints. |
A call made with a key that lacks the required scope returns 403. See Errors for the full status table.
List keys#
Returns the public (non-secret) representation of every key on your tenant, newest first. Plaintext secrets are never included.
curl https://api.neolife.health/v1/developer/keys \
-H "Authorization: Bearer $NEOLIFE_API_KEY"
[
{
"id": "key_7Qw2eR",
"name": "shopify-fulfillment-worker",
"environment": "sandbox",
"prefix": "nk_sandbox_9f3c1a7e",
"scopes": ["orders:write", "orders:read"],
"createdAt": "2026-07-06T14:12:00Z",
"revokedAt": null
}
]
Revoke a key#
Revocation is irreversible and takes effect immediately — the next request made with a revoked key fails authentication. It's also idempotent: revoking an already-revoked key is a no-op that returns the same key, and revoking a key that doesn't exist on your tenant returns 404.
curl -X DELETE https://api.neolife.health/v1/developer/keys/key_7Qw2eR \
-H "Authorization: Bearer $NEOLIFE_API_KEY"
{
"id": "key_7Qw2eR",
"name": "shopify-fulfillment-worker",
"environment": "sandbox",
"prefix": "nk_sandbox_9f3c1a7e",
"scopes": ["orders:write", "orders:read"],
"createdAt": "2026-07-06T14:12:00Z",
"revokedAt": "2026-07-06T16:40:00Z"
}
Rotating a key#
There's no in-place rotation — rotate by creating the replacement, then revoking the old one:
- Create a new key with the same environment and scopes.
- Deploy the new key to your secret store and roll it out.
- Revoke the old key once nothing is using it.
Because create and revoke are independent calls, you get a clean overlap window with no downtime.
Related#
- Authentication — how keys travel on requests, sandbox vs. live, and least-privilege guidance.
- API reference — base URL, versioning, errors, and rate limits.