Skip to main content

Asynchronous operations

Commands to a product travel from the API through a Gateway and over Bluetooth, which takes seconds, not milliseconds. So the API answers straight away with an event_id, and tells you the result later, over the realtime connection. This page covers the whole lifecycle.

It applies to POST /v2/products/{id}/state and POST /v2/products/{id}/settings.

The lifecycle​

StepWhoWhat happens
1YouConnect to realtime, and wait until you're connected.
2You → APISend the command, for example {"operation": "open"}.
3APIChecks the command can run. If not, answers with an HTTP error (below) and stops.
4API → youAnswers 200 with {"success": true, "data": {"event_id": "a1b2c3d4"}}. The device hasn't moved yet.
5API → GatewaySends the command to the first candidate Gateway and waits up to 30 seconds for its answer.
6Gateway → productRelays the command over Bluetooth; the product acts and reports back.
7aAPI → youSuccess: a lot_change event with the same event_id and the product's new state.
7bAPI → youFailure: a gateway_error event with the same event_id.

event_id is 8 hexadecimal characters.

How the Gateway is chosen​

The candidates are the Gateways that currently see the product over Bluetooth. The API tries them one at a time, strongest signal first, waiting up to 30 seconds for each:

  • If a Gateway answers that the operation worked, you get lot_change.
  • If it times out, or fails for a reason another Gateway might not hit (for example a Bluetooth error), the API moves on to the next Gateway.
  • If the product itself reports a problem that no other Gateway can fix (type 0, 1, 5, 6, 7 or 8 below: for example jammed, or a car on top), it stops there and you get gateway_error.
  • If every Gateway fails, you get gateway_error with the last error.

So with several Gateways in range, a result can take a multiple of 30 seconds.

Errors before anything is sent​

These come back as HTTP errors in step 3, and nothing is sent to the device:

HTTPCodeMeaningWhat to do
40330The product's subscription doesn't include remote control.See Plans and permissions.
4034The product isn't visible to your token.Check the product is on a lot your token can see; see Data model.
4046No product with that id.Check the id.
403214An earlier operation on this product hasn't finished.Wait for its result; don't retry in a loop.
403704No Gateway currently sees the product.Check the Gateway is online, on the same lot and in range.
403206The product isn't paired.Pair it with the Connect app.
42223Invalid body, for example an unknown operation.Fix the request.

gateway_error types​

gateway_error
{
"type": 5,
"event_id": "a1b2c3d4",
"data": { "id": 123, "name": "Spot 12" },
"message": "Device jammed"
}

When no Gateway answered in time, type is the string "Timeout" and there's no message. Otherwise it's a number. These are not the HTTP error codes.

typemessageTries the next Gateway?
0Auth errorNo
1Invalid guest keyNo
2Device disconnectedYes
3Bluetooth errorYes
4Device not foundYes
5Device jammedNo
6Car on topNo
7Sensor dirtyNo
8Device not initializedNo
9Rtcc not setYes
10Device busyYes
11Unknown errorYes
"Timeout"(none)Yes

wait_for_completion​

POST /v2/products/{id}/state accepts an optional wait_for_completion (default true). It's passed on to the Gateway, which by default waits until the product reports it has reached the new state. Set it to false for a brain without input sensors, which can't report an open or closed state. It doesn't change the HTTP response: you always get the event_id straight away.

Writing a client​

  1. Connect to realtime before sending commands, with the same API token, so you can't miss the result.
  2. Keep the pending event_ids in a map, and resolve each on the lot_change or gateway_error that carries it. The result can arrive before your HTTP call returns: buffer results you haven't matched yet.
  3. Ignore event_ids you didn't send. Your connection also receives operations started by others (the Connect app, other users) and automatic ones, such as Parklio setting a device's clock.
  4. Give up client-side after a timeout of your choice, and re-read the product with GET /v2/products/{id} to see where it ended up.
  5. One operation per product at a time. A second command while the first is pending gets 214.

There's no REST endpoint to look up a result by event_id, and no replay: if you were disconnected when the event was sent, re-read the product's state over REST.

A working example is in the Quickstart.