Authentication and API keys
How to create a key, send it, keep it safe, and tell the two kinds of credential apart.
Every request carries a credential as a bearer token:
Authorization: Bearer xpk_live_…There are two kinds of credential, and they are not interchangeable.
| Workspace API key | Device token | |
|---|---|---|
| Prefix | xpk_live_ or xpk_dev_ | xpd_live_ or xpd_dev_ |
| Can do | Whatever its scopes allow, across the workspace | Post readings, events and heartbeats for one device, nothing else |
| Lives on | A server, a script, an integration you run | The device itself: a Raspberry Pi, a gateway, a microcontroller |
| Created in | Settings → Integrations → API Keys | With the API, using a workspace key (see Device tokens) |
Plans and access
Three things bound what a key can do: its scopes, its owner's role, and the workspace's plan. A key never does more than its owner can in xPlant.
By plan
| Plan | What API keys can do |
|---|---|
| xPlant+ Teams, Enterprise | The whole API: every scope. |
| Hobby, Pro Lab | Connect devices only: read:devices, write:devices, write:sensor_readings and write:device_events. Keys can register devices, manage their tokens, and post their readings and events. They can't read sensor readings back; that data is visible in xPlant. |
| Free | No API access. Every request answers 402 PAID_PLAN_REQUIRED. |
A call outside what the plan includes answers 402 PAID_PLAN_REQUIRED. See plans to upgrade. Your plan's allowances still apply too: registering devices beyond the plan's allowance answers 402 DEVICE_LIMIT_REACHED.
By role
A key acts with its owner's role in the workspace, as it is at the time of each request. If the owner's role changes, the key follows.
| Scopes | Minimum role of the key's owner |
|---|---|
read: scopes, except the two below | Any active member |
write: scopes, except the one below | member |
read:pricing, read:commerce, write:demand | manager |
Roles rank owner > admin > manager > member > viewer > guest. A call that needs more than the owner's role answers 403 FORBIDDEN, and the message names the scope and the role it needs, for example:
{
"ok": false,
"data": null,
"error": "This key's owner is a viewer in this workspace, which cannot use write:tasks (needs member or above). A key never does more than its owner can in xPlant.",
"code": "FORBIDDEN"
}The wording can change; branch on code. As a rule of thumb, 402 is about the plan, and 403 is about the role or a missing scope.
When you create a key
You can only grant scopes that your role and your plan allow. A scope above your role is refused with 403, and one above your plan with 402, and both messages name the scopes involved.
Check before you call
GET /me returns the key's scopes (what it was created with), effectiveScopes (what it can use right now, after the role and plan limits), the owner's role, and apiAccess: full on Teams and Enterprise, devices on plans whose keys can connect devices only.
Devices after a plan lapses
Device tokens keep posting readings, events and heartbeats after a plan lapses, so sensors don't go quiet. New devices and new tokens follow the plan's device allowance.
Enterprise customers can scope organisation-specific integrations and API requirements with us: support@xplantpro.com.
Creating a key
- Open Settings → Integrations → API Keys in xPlant.
- Name the key after what will use it ("Nightly task sync", "Grow room dashboard"). You'll thank yourself when you need to revoke one.
- Choose its scopes. A key gets exactly what you tick, and nothing by default. See Scopes for what each one allows and some common setups.
- Copy the key straight away. It is shown once. If you lose it, create a new one and revoke the old.
Scopes are fixed when a key is created. To change what an integration can do, create a new key with the scopes it needs, move the integration to it, then revoke the old key. Rotating a key in xPlant issues a new secret with the same name, scopes and environment.
A workspace can have up to 10 active keys at a time.
Live and dev keys
The xpk_live_ and xpk_dev_ prefixes are labels for your own bookkeeping. Both act on your real workspace, with the same data and the same limits. There is no sandbox. Use a dev key to keep test traffic separate in your records, not to protect production data.
What a key can reach
- One workspace. A key belongs to the workspace it was created in and can never read or write another workspace's records. If you belong to several labs, each needs its own key.
- Its scopes, and nothing more. No scope implies another;
write:tasksdoes not grantread:tasks. - A record in another workspace looks the same as one that doesn't exist. Both answer
404 NOT_FOUND, so a key can't be used to probe for ids.
Call GET /me to see which key you're using and every scope it holds. It needs no scope.
When a key stops working
| You get | Because |
|---|---|
401 UNAUTHORIZED | The key is missing, mistyped or revoked, or the person who created it has left the workspace. |
402 PAID_PLAN_REQUIRED | The workspace's plan doesn't include this call. Teams and Enterprise include the whole API; Hobby and Pro Lab keys can connect devices only; Free has no API access. See Plans and access. |
403 FORBIDDEN | The key lacks the scope this endpoint needs, or its owner's role is below what the scope needs. The error text says which, e.g. Missing scope: write:tasks. |
403 DEVICE_TOKEN_NOT_ACCEPTED | You sent a device token to an endpoint that needs a workspace key. |
A key is tied to the member who created it. When someone leaves the workspace, their keys stop working, so create keys for long-running integrations from an account that will stay.
Keeping keys safe
- Keep keys in environment variables or a secrets manager, never in source code or a repository.
- Never put a workspace key on a device. A box on a shelf, in a room other people walk through, should carry a device token that can only post its own readings.
- Never embed a key in a web page or a mobile app. Anyone who opens it can read it. Call the API from your own backend instead.
- Give each integration its own key with only the scopes it needs, so you can revoke one without breaking the others.
- If a key leaks, revoke it in Settings → Integrations → API Keys at once, then create a replacement.