---
title: "Create Farm Recall"
method: POST
path: "/api/v1/customer/farms/{farm_id}/recall"
tags: ["customer launch intents"]
---

# Create Farm Recall

`POST /api/v1/customer/farms/{farm_id}/recall`

## Request

- Base URL: `https://api.brumby.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.brumby.com/api/v1/customer/farms/{farm_id}/recall`
- Auth: none declared

Recall the aircraft of this farm. The phone's ABORT button ends here.

THE DEVICE IS RESOLVED, NEVER SUPPLIED. Same rule as the customer mission route: a
phone naming its own target could recall somebody else's aircraft by typing a
different id. The farm's one active N100 is looked up here; two of them is a 409 and
none is a 404, because guessing which to recall is not a thing software should do.

WHAT HAPPENS NEXT, so the shape of this handler makes sense: the row is published
retained to the dock, whose supervisor holds it as STATE -- not gated on preflight,
not gated on the aircraft being airborne -- and dock-mav then sends BRUMBY_DOCK_ABORT
at 1 Hz for as long as it stands, deliberately even into a link that reads stale. The
Cube changes its own flight mode on receipt and flies the recovery itself. So this
endpoint's job is only to make the standing instruction exist; nothing downstream is
waiting on this response.

THE IDEMPOTENCY KEY IS REQUIRED, for the reason the admin route gives: a retried POST
without one places a second intent with a second id, and two rows are two recalls.
Here it also matters in the other direction -- a panicking operator pressing ABORT
four times should place ONE recall, not four.

## Path parameters

- `farm_id` string, required

## Headers

- `Idempotency-Key` string, nullable
- `X-Brumby-Customer-User-Id` string, nullable
- `X-Request-Id` string, nullable

## Request body

- FarmRecallCreate: A customer recalling their farm's aircraft, from the phone. THE NARROW SURFACE ON PURPOSE. ``LaunchIntentCreate`` takes an intent_type and a free ``parameters`` dict because an admin cockpit legitimately places every kind of intent; a customer app places exactly one, so this cannot express any other. The intent_type is not a field here at all -- it is RECALL by construction. ``reason`` is capped at the width of the MAVLink field that eventually carries it (``BRUMBY_DOCK_ABORT.reason``, char[16]). Capping here rather than truncating at the wire means the operator's note reaches the aircraft whole or not at all, instead of being silently cut four hops later.
  - `action` 'rth' | 'recover' | 'cancel_launch'
  - `reason` string

## Response `201`

Successful Response

- LaunchIntentResponse
  - `intent_id` string, uuid, required
  - `device_id` string, required
  - `intent_type` 'launch' | 'open' | 'close' | 'hold' | 'recall' | 'clear_fault', required: Doc 04 §1.1's intent vocabulary. ``launch`` and ``recall`` have dock seams. The rest are declared because the dock's own contract declares them, and a type it does not handle is logged and ignored rather than mistaken for a launch.
  - `state` 'pending' | 'published' | 'acknowledged' | 'refused' | 'withdrawn' | 'failed', required: FleetOps-side lifecycle of one intent. Shorter than a diagnostic action's, and the difference is the point: an intent is RETAINED, so the broker owns redelivery. There is no publishing/accepted dance to track, because the dock may collect it minutes later on reconnect and that is correct rather than late. ``WITHDRAWN`` is a real state and not a deletion: clearing a standing intent means publishing an empty retained payload, which is an act that has to be recorded.
  - `parameters` object, nullable, required
  - `requested_by_actor` string, required
  - `valid_from` string, date-time, required
  - `valid_until` string, date-time, required
  - `published_at` string, date-time, nullable, required
  - `withdrawn_at` string, date-time, nullable, required
  - `acknowledged_at` string, date-time, nullable
  - `disposition` 'accepted' | 'refused' | 'ignored': What the dock reported doing with a collected intent, verbatim. ``ignored`` is a type with no supervisor seam (open/close/hold today) — recorded as REFUSED state-wise, but the word is kept because "the dock cannot do this yet" and "preflight said no" are different answers.
  - `disposition_detail` object, nullable
  - `last_error` string, nullable, required
  - `created_at` string, date-time, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/brumby/apis/brumby-platform-api.md) - [All operations](https://skmtc.dev/brumby/apis/brumby-platform-api/llms.txt) - [OpenAPI document](https://skmtc.dev/brumby/apis/brumby-platform-api/revisions/fe185e20813e?raw)
