Vehicle commands

Send the same vehicle commands as the FleetBold app with `commands:all`; results are pull-only.

Draft

Before sending vehicle commands, make sure the vehicle is not currently being operated — some commands (e.g. engine cut) can disable the vehicle.

FleetBold does not define a separate command catalog for apps. Each command is identified by the id of the FleetBold app command it mirrors (for example lock_unlock_command, fleetbold/engine_cut), takes that command's parameters and goes through the same permission checks, billing rules, device transports and per-user Tesla quota as when the user taps the button in the app. One difference: a FleetBold device command can go to any FleetBold tracker of the vehicle you can reach (device_id), not only to the one the app shows as primary. The full list is in the API reference; GET /v1/vehicles/{vehicle_id}/capabilities tells you which ones a vehicle accepts right now and GET /v1/vehicles/{vehicle_id}/devices/capabilities the same per tracker.

Scope: commands:all

  • A single critical scope, commands:all, enables every command, including engine cut. The consent page shows it in red; the first time a user grants it, the page asks for an extra confirmation (later authorizations show it as already granted). While your app is not live or the scope is still pending review, the page also shows a vehicle-operation warning.
  • Development apps: the owner and the app's test users can grant and use it on the vehicles they share.
  • Live apps: FleetBold approves commands:all explicitly in the Go-live review. Successful test commands are not required, but the reviewer sees them; if your app cut an engine while testing, recover it with fleetbold/engine_recover.
  • Personal access tokens with commands:all must have an expiry (otherwise 403 command_not_allowed).
  • commands:all never widens FleetBold's permissions: in an organization context the member still needs FleetBold's permission for each command (403 command_not_permitted), and past-due accounts get 402 payment_past_due like in the app.

Which tracker receives the command

  • Tesla commands go to the vehicle (the user's linked Tesla account) and take no device_id; with one they answer 422 command_not_supported (reason: not_supported_by_device).
  • FleetBold device commands (fleetbold/…) go to the tracker named by the optional top-level device_id — a dev_… id from GET /v1/vehicles/{vehicle_id}/devices, primary or not. Without it, FleetBold picks the first tracker that can take the command (primary first, then oldest).
  • A tracker takes FleetBold device commands only when it is activated and has a subscription (otherwise 422, reason: no_active_device); third-party and built-in trackers take none (reason: not_supported_by_device); a device_id that is not one of the vehicle's trackers in your context answers 404 device_not_found. Which tracker is primary never decides who may send.
  • The command resource names the tracker in device_id. GET /v1/vehicles/{vehicle_id}/devices/{device_id}/capabilities lists the commands of one tracker.
  • Telemetry still follows the primary tracker: a command to another tracker works, but what that tracker reports does not appear in the vehicle's /v1 data until it is made primary.

Sending a command

Engine cut (FleetBold device)bash
curl -X POST https://partners-api.fleetbold.com/v1/vehicles/$VEHICLE_ID/commands \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"command":"fleetbold/engine_cut"}'
  • Idempotency-Key is required: a retry with the same key never sends the command twice (see the Idempotency guide).
  • The answer is 202 Accepted with a command resource (cmd_…, also in the Location header), even when the command then failed at the vehicle: read status and failure.
  • Tesla commands answer succeeded or failed right away. FleetBold devices answer sent, then succeeded, failed or — when nothing confirms before confirm_by — expired.

Results are pull-only

There are no command webhooks. Poll GET /v1/commands/{command_id} until the status is succeeded, failed or expired; while it is not final the answer carries Retry-After: 2 (a polling hint). Back off gradually.

Failures: outcome and retry_safe

  • not_executed: nothing reached the vehicle — fix the cause, then resend with a new key.
  • rejected: the provider answered "no" — safe to resend.
  • unknown: the command may have executed — never resend blindly (engine cut!); check the vehicle's state first.
  • New failure codes can appear: always decide by outcome and retry_safe.

Concurrency and loop protection

Commands have their own budget (30 units / min per connection, 300 per app by default; see Rate limits) and FleetBold protects vehicles from buggy integrations. None of this applies to the FleetBold app itself. The numbers below are the defaults; your effective values are in the app Overview → Rate limits card.

  • One command at a time per vehicle. Per connection and vehicle, at most one command (max_inflight_per_vehicle) may be queued or sending. Another answers 409 vehicle_command_in_flight with the ids in progress and Retry-After. A sent command waiting for the device does not count.
  • Identical commands are answered, not repeated. The same command with the same parameters to the same tracker while an earlier one is queued, sending or sent returns the earlier command (202, its cmd_… id, header Command-Deduplicated: true); nothing is sent again.
  • Loop guard. Only commands that reached the vehicle path count. The same command 5 times within 120 s, an on/off pair (lock/unlock, engine cut/recover, …) flipping 10 times within 600 s, or 5 failed executed attempts within 300 s start a cool-down: that command (every command of the pair for a toggle) answers 429 command_loop_suspected (loop, command, Retry-After) for 10 minutes. Other commands keep working.
  • Blocks. 3 cool-downs of one connection and vehicle within an hour block every command from that connection to that vehicle for 24 h: 429 command_loop_blocked (vehicle_id, blocked_until, Retry-After). Your team is e-mailed and the block shows in the console (a banner and the Overview → Command blocks card). The block ends on its own; only FleetBold can clear it earlier.
  • Engine recover is exempt. fleetbold/engine_recover is never cooled down, blocked or limited by the in-flight rule, so an engine cut can always be reverted through the API. A second identical recover while the first is still pending answers the first one's command_id (Command-Deduplicated: true) instead of sending it again.
  • When the rate-limit store is unavailable every check answers 503 service_unavailable (reason: redis_unavailable, Retry-After: 5) instead of running unchecked.

There are no per-command or per-vehicle limits on volume. The connected user and the vehicle owners are e-mailed when your app sends a command.