Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.amps.ai/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks are how Amps pushes events to you. When an action reaches a terminal state or a device’s connection status changes, a signed HTTP POST lands on your registered endpoint. Delivery is retried with exponential backoff; endpoints are managed from the dashboard. Subscribe to anything you would otherwise poll. Polling is the right default for dashboards where the user accepts visible cache freshness. Events are the right default for any state change a user is waiting on. Pick once at integration time and the rest of the design follows. Events are also how you give end users fast feedback. A user waiting for a charge to start expects the UI to update when the device confirms; a polling cadence that runs every minute can’t deliver that.

Event taxonomy

Two categories exist. Lifecycle events track device connection state. Push-action events track command outcomes.
EventCategoryWhen it fires
device.connectedLifecycleA new device finishes registration via the Auth Journey.
device.reconnectedLifecycleAn existing device’s credentials are refreshed.
device.disconnectedLifecycleStored credentials become invalid. May carry a reconnectionUrl when the OEM’s auth flow supports re-entry.
push.completedPushThe OEM accepted the command. The action is in completed.
push.failedPushThe OEM rejected, or a transient failure exhausted the path. The action is in failed.
Schedule lifecycle events (schedule.created, schedule.updated, schedule.cancelled, schedule.slot_failed, schedule.slot_skipped) flow through the same delivery path. They are documented under scheduling.
completed means the OEM API accepted the command, not that the device verified end-state. Verifying end-state would mean polling the OEM after every command, doubling latency without telling you anything the next pull cannot. Tail the device pull or wait for a state-change webhook if end-state confirmation matters.

Payload shape

Webhook bodies are flat; the event type is delivered in headers (svix-id, svix-timestamp, svix-signature) rather than in the body. Lifecycle events carry the device identifiers:
{
  "deviceId": "device_abc123",
  "deviceType": "battery",
  "timestamp": "2026-06-01T10:14:23Z"
}
device.disconnected may add a reconnectionUrl pointing at the Auth Journey in reconnection mode, when the OEM’s auth flow supports re-entry:
{
  "deviceId": "device_abc123",
  "deviceType": "battery",
  "timestamp": "2026-06-01T10:14:23Z",
  "reconnectionUrl": "https://auth.amps.ai/?reconnect=true&token=..."
}
Push-action events carry the action state loaded fresh at delivery time:
{
  "actionId": "action_xyz789",
  "deviceId": "device_abc123",
  "actionType": "battery:set_operation_mode",
  "parameters": { "mode": "charge", "target": { "value": 90, "unit": "percent" } },
  "result": { "success": true, "message": "Mode applied" },
  "completedAt": "2026-06-01T18:00:04Z"
}
The payload is loaded fresh from the action record at delivery time, not built from the event that triggered the webhook. The payload always reflects current truth on delivery. Re-fetching the action returns the same payload.

Delayed delivery

Webhook delivery is delayed by a fixed interval after the trigger:
EnvironmentDelay
Live10 seconds
Sandbox180 seconds
The sandbox delay gives you time to set up a tunnel and an endpoint between submitting the action and the webhook landing. The live delay leaves room for any post-processing that should complete before you receive the event (audit trail written, response cache populated). Webhook delivery is isolated from the dispatch path, so webhook volume cannot affect command latency.

Retries

A 2xx from your endpoint marks the delivery successful. Anything else triggers a retry on a backoff schedule. The retry policy and delivery history are configurable from the dashboard. Idempotency on your side is mandatory. Treat each event as potentially deliverable more than once. Dedupe by actionId for push events and by deviceId plus type plus timestamp for lifecycle events.

Signature verification

Every webhook carries three headers (svix-id, svix-timestamp, svix-signature). Verify the signature before processing; the SDK reads all three. The signature is computed over the raw request body; verifying after JSON parsing or whitespace normalisation will fail.
import { Webhook } from 'svix';

const webhook = new Webhook(process.env.WEBHOOK_SECRET);

app.post('/webhooks', (req, res) => {
  try {
    const verified = webhook.verify(req.rawBody, req.headers);
    handleEvent(verified);
    res.status(200).send('OK');
  } catch {
    res.status(400).send('Invalid signature');
  }
});
The webhook secret is per-endpoint and visible in the dashboard. Rotate it from the dashboard; rotation does not affect your API key. The full reference, including language-specific examples, is at webhook security.
Never process webhooks without verifying signatures. An unverified endpoint accepts forged events from anyone who can reach it.

Endpoint configuration

You get a separate webhook consumer per environment. Webhook delivery targets the consumer matching the API key that produced the event. Sandbox events go to your sandbox consumer; live events go to your live consumer. Configure endpoints from the dashboard’s webhook settings. Multiple endpoints per environment are supported. Each endpoint is delivered independently, so failing one does not affect the others.

Operational behaviour

A few specifics worth knowing:
ScenarioBehaviour
Push action delivered while still in a non-terminal stateSkipped at the delivery step; the task is acknowledged.
Action ID present in the task but absent from storageSame as above. Logged and acknowledged.
Pull failure with INVALID_CREDENTIALSEmits a device.disconnected lifecycle webhook in addition to whatever the operation produced.
Push failure with INVALID_CREDENTIALSEmits both a push-action webhook and a device.disconnected lifecycle webhook.
Webhook delivery URL not configuredPush and pull operations complete without error; no webhook is scheduled. The misconfiguration is logged.

What webhooks do not do

  • No per-event-type filtering at the subscription level. Every endpoint receives every event in scope. Dispatch from your handler.
  • No batch delivery. Each event is one HTTP request.
  • Replay is exposed through the dashboard rather than an in-product UI.

Sandbox vs live

Sandbox webhooks let you test your handler before you have a live device. Simulated devices emit realistic action lifecycle events. The 3-minute sandbox delay covers initial wiring; the 10-second live delay matches production once you switch keys. The same delivery infrastructure backs both environments: same signature scheme, same retry behaviour, same payload shape. Switch from sandbox to live by switching the API key and updating the consumer endpoint. Your handler logic does not need to change.

Frequently asked questions

How quickly are webhooks delivered after an action completes?

Live webhooks land roughly 10 seconds after the action reaches its terminal state. Sandbox webhooks land after 180 seconds. Webhook delivery is isolated from the dispatch path, so webhook volume does not affect command latency. The sandbox delay exists for developer ergonomics: it gives you time to set up a tunnel and an endpoint between submitting the action and the webhook landing.

What happens if my webhook endpoint is down?

The platform retries on a backoff schedule. A 2xx from your endpoint marks the delivery successful; anything else triggers retry. The retry policy and visible delivery history are configurable from the dashboard. Persistent failures eventually exhaust the retry budget and stop. Idempotency on your side is mandatory: treat each event as potentially deliverable more than once. Dedupe by actionId for push events and by deviceId plus type plus timestamp for lifecycle events.

How do I verify a webhook signature?

Every webhook carries an svix-signature header computed over the raw request body. Verify before processing using the Svix SDK or its equivalent in your language. The signature is computed over raw bytes, so verifying after JSON parsing or whitespace normalisation will fail. The webhook secret is per-endpoint and surfaced in the dashboard. Rotate it from the dashboard; rotation does not affect your API key. Never process webhooks without verifying signatures.

What does completed mean in a push.completed webhook?

It means the OEM API accepted the command, not that the device verified end-state. Verifying end-state would require polling the OEM after every command, doubling latency without adding value the next pull cannot deliver. Tail the device pull or wait for a state-change webhook if end-state confirmation matters. The webhook payload is loaded fresh at delivery time, so it reflects the latest truth on delivery.

Can I filter which events my endpoint receives?

Not at the subscription level. Every endpoint receives every event in scope. Use your handler to dispatch on the event type from the svix-id and headers. Multiple endpoints per environment are supported and each is delivered independently; failing one endpoint does not affect delivery to the others. Filtering, batching, and replay are exposed through the dashboard.

Scheduling

Action lifecycle states that produce webhooks.

Auth Journey

device.connected fires when registration completes.

Webhook Security

Signature verification reference.

Device State

Polling versus webhook patterns for state changes.
For a worked walkthrough wiring a webhook handler, see the cookbook: subscribe to webhooks.