API keys
Every API request carries an API key in thex-api-key header. Each key is validated on every request; metadata stored on the key drives environment routing and customer scoping.
Bearer-prefixed forms are accepted:
customerId and environment baked into its metadata at creation time. Environment is one of sandbox or live, fixed at issuance. A sandbox key never accesses live data, a live key never accesses sandbox data, and the environment cannot be overridden via request parameters. The split is absolute.
| Prefix | Environment |
|---|---|
sk_test_* | Sandbox |
sk_live_* | Live |
Authentication errors
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | No API key in the request. |
INVALID_API_KEY | 401 | Key is unrecognised, malformed, revoked, or soft-deleted. |
EXPIRED_TOKEN | 401 | Key has passed its expiry. |
RATE_LIMIT_EXCEEDED | 401 | Key has exceeded its rate ceiling. |
INSUFFICIENT_PERMISSIONS | 403 | Key lacks the permission for the requested operation. |
LIVE_ACCESS_DISABLED | 403 | Live key used by a customer not enabled for live access. |
error.message, the audit trail persists, and the key body never executes again.
See the error envelope for the full response shape.
Sandbox
| Sandbox | Live | |
|---|---|---|
| Devices | Simulated, deterministic | Real OEM hardware |
| Credentials | None required | Real OEM credentials per user |
| Allowances | Unlimited | Per-OEM and global caps apply |
| Use | Build, test, demo | Customer traffic |
LIVE_ACCESS_DISABLED. Sandbox keys skip that check.
Sandbox shows every device the platform supports. Live shows the OEMs your Customer App is configured for, filtered to the tiers you are entitled to. See capabilities for the availability tier model.
Sandbox device behaviour
Sandbox devices return deterministic data driven by UTC time-of-day, so the same call at the same wall-clock instant returns the same shape across runs. Useful when you’re writing fixtures or asserting against expected values.| Device type | Morning (06-09 UTC) | Midday (09-15 UTC) | Evening (15-21 UTC) | Night (21-06 UTC) |
|---|---|---|---|---|
| Vehicles | Plugged in, 80-95% | Unplugged, level decreasing | May plug in for overnight | Plugged in, charging |
| Batteries | Discharging for morning load | Charging from solar | Discharging for peak usage | Idle or slow charging |
| Solar inverters | Ramping up | Peak production | Declining | No production |
Live access
Live access requires explicit enablement on your account. Until that flag is set, every live API key returns 403. Once enabled, live keys access live data and reach real OEM hardware.Environment isolation
Sandbox and live data are stored in fully isolated schemas. Customer accounts are shared across the two; devices, credentials, actions, and schedules are not. Queries route to the correct schema based on the environment your API key carries.Device access control
Beyond the API key check, every device-scoped request verifies the device belongs to your account in the request’s environment.| Code | HTTP | Trigger |
|---|---|---|
DEVICE_NOT_FOUND | 404 | Device does not exist, or exists but is not linked to your account in this environment. |
The Auth Journey
End users connect their OEM accounts through the Auth Journey, a hosted flow you embed in your app via a Plaid Link-style hand-off. You passappId and a userId (your own end-user identifier) to the URL, the journey walks the user through device connection, and redirects back to your redirectUrl on success.
The step sequence: device type selection, OEM selection (filtered by your Customer App’s supported OEMs), auth method choice (where the OEM offers more than one), credential or API-key entry, MFA verification (if the OEM requires it), device selection, consent collection, success and redirect.
Browser back navigation is disabled after the credentials step. Once credentials are in flight to the OEM, allowing back would leave the session inconsistent. Credentials never touch browser storage; they live only in component state. Short-lived signed tokens carry context between steps and prevent tampering.
When credentials expire (OEM revokes a session, the user changes their password), Amps emits device.disconnected with a reconnectionUrl. The user follows it, the journey runs in reconnection mode skipping device-type, OEM, and device selection, the credential record refreshes, and device.reconnected fires. See webhooks.
Each Customer App declares redirectUrl, reconnectRedirectUrl, logoUrl, appName, and a list of supported OEMs. Manage Customer Apps from the dashboard.
Device lifecycle
Once a user begins, every device follows the same lifecycle:Device allowances
Every account has two caps:| Cap | Scope |
|---|---|
| Global | Total devices across all OEMs. |
| Per-OEM | Devices per manufacturer. |
Public routes
A small number of routes are public and bypass authentication. The OpenAPI spec at/openapi.json and a few health endpoints fall in this category. The full list is in the API reference; everything else requires a valid key.
Frequently asked questions
How do sandbox and live environments differ?
The same code paths, the same cache rules, the same response shapes. Sandbox uses simulated devices that return deterministic data with realistic timing; live talks to real OEM hardware. Every code path the live environment exercises is exercised in sandbox: the same auth guards, the same cache layer, the same async write path, the same webhook delivery. The only divergence is at the OEM-call layer. Sandbox keys never reach live data; live keys never reach sandbox data.What happens if I send a sandbox key to the live host?
Both environments live behind the same host. The split is enforced at the API key, not the host: a key prefixedsk_test_* always routes to sandbox, a key prefixed sk_live_* always routes to live. The environment is fixed at issuance and stamped into the key’s metadata. Callers cannot override it via request parameters. A live key against a customer not yet enabled for live returns 403 LIVE_ACCESS_DISABLED.
How do API keys map to organisations?
Every key carriescustomerId baked into its metadata at creation time. The customer record is shared across environments; device records and everything below are isolated by environment. Beyond the API key check, every device-scoped request verifies the device belongs to the authenticated customer. A device that exists but is not linked to this customer returns 404, not 403, to avoid leaking the existence of devices owned by other customers.
What is the Auth Journey?
A hosted flow embedded in your application via Plaid Link-style hand-off. End users connect their OEM accounts through it; the journey walks them through device-type selection, OEM selection, credential entry, MFA, device selection, consent, and registration. Credentials never touch browser storage; they exist only in component state. Short-lived signed tokens carry context between steps. On success, the journey redirects back to yourredirectUrl and the platform fires a device.connected webhook.
How do device allowances work?
Two caps exist on every customer: a global cap (total devices across all OEMs) and a per-OEM cap. Devices that exceed an allowance are flagged as overage and access is restricted. Overage is preferable to a hard rejection at registration time: it lets trial flows continue without losing data, and reducing an allowance does not silently delete devices. Allowances are managed from the dashboard.Related concepts
Capabilities
Per-device declaration of supported commands and parameters.
Webhooks
device.connected, device.disconnected, device.reconnected.Error Envelope
INVALID_API_KEY, LIVE_ACCESS_DISABLED, DEVICE_NOT_FOUND.Link UI
Embedding the Auth Journey in your app.