---
title: "Move Mob"
method: POST
path: "/mobs/{id}/move"
tags: ["Mobs"]
---

# Move Mob

`POST /mobs/{id}/move`

## Request

- Base URL: `https://api.purplegrain.com/api/v1`
- URL: `https://api.purplegrain.com/api/v1/mobs/{id}/move`
- Auth: HTTP bearer

Put a mob in a paddock.

**A move is a record, not a field.** There is no writable location
anywhere on a mob: this endpoint writes one completed `move_stock` record
carrying the origin, the destination and the composed line "Moved the
merino wethers from Middle Run to Top 40", and `current_paddock_id` is
derived from that record. So the property's diary can never disagree with
its map, reopening the record un-places the mob, and removing the
destination paddock un-places it too.

A POST rather than a PUT because it creates something. The origin is
resolved server-side from wherever the mob is now, and may be none — the
first move of a mob that has never been placed is the prototype's
"Put in a paddock", and its sentence simply omits the "from" clause.

The response is the **mob** at its derived placement, with its counters
already updated. The record itself is read back with the mob's board
(a task read), which is what a client refetches anyway.

`completed_at` records a move after the fact. The record is always
written, but the placement is still whatever the newest completed record
says — so back-dating a move behind an existing newer one files the diary
entry and leaves the pin where it was. The rejection below compares
against the mob's placement *today*, not its placement on the supplied
date.

The destination must be a live paddock on the mob's own property, and not
the one the mob is currently in. Requires organization edit rights.

## Path parameters

- `id` string, required

## Query parameters

- `include` string

## Request body

- MobMoveModelAttributes: Flat attributes-adapter request body (Content-Type application/json) for a mob move. The destination is a resource identifier object ({ id, type }) directly under `data`. Equivalent JSON:API (nested) shape: `MobMoveModel` sent as application/vnd.api+json.
  - `data` object, required
    - `completed_at` string, date-time, nullable: When the move happened. Omit or send null for "now".
    - `capture_source` string, nullable: How the move was captured — `voice`, `typed`, `agent` or `import`. `form` is stored as `typed`. Defaults to `typed`.
    - `to_paddock` object, required: The destination — a live paddock on the mob's own property.
      - `id` string, required
      - `type` 'paddock'

## Response `200`

The mob at its derived placement — the new paddock, unless an older `completed_at` put the move behind an existing one.

- MobsShowResponseAttributes
  - `data` MobModelAttributes: Single mob in attributes-adapter shape (Accept application/json).
    - `id` string
    - `type` string
    - `slug` string: Unique within its parent (a property per owner; a paddock or mob per property); generated from the name and renamed with it. The old slug keeps resolving. See `resolveLink`.
    - `web_path` string: The address on the web. Present when read directly.
    - `url` string: The whole link; carries the property's `?share=` token when it is shared by link. Present when read directly.
    - `name` string
    - `head_count` integer, nullable: How many head are in the mob, as a number — never a display string. Null is a real state.
    - `withholding` object, nullable: Is the mob under a withholding period or export slaughter interval right now? The latest drench record whose safe-for-slaughter or export date is still ahead, or null. **Derived, not stored.** Read-only.
      - `task_id` string
      - `record_id` string: The DrenchRecord id.
      - `safe_for_slaughter_on` string, date, nullable
      - `export_eligible_on` string, date, nullable
      - `products` string[]
    - `current_paddock_id` string, nullable: Where the mob is right now, derived from the most recent completed record carrying a destination (see `MobModel`). Read-only — move a mob with `moveMob`.
    - `archived` boolean: An archived mob leaves the map and the lists; its records stay on the property.
    - `archived_at` string, date-time, nullable
    - `record_count` integer: Completed rows on this mob — its diary.
    - `open_task_count` integer: Pending rows on this mob.
    - `last_record_at` string, date-time, nullable
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `farm` object: Present when include=farm
  - `meta` PaginationMeta
    - `current_page` number
    - `next_page` number, nullable
    - `prev_page` number, nullable

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `422`: A missing destination, a paddock on another property, an archived paddock, or the paddock the mob is already in

---

[API](https://skmtc.dev/purplegrain/apis/purple-grain-api.md) · [All operations](https://skmtc.dev/purplegrain/apis/purple-grain-api/llms.txt) · [OpenAPI document](https://skmtc.dev/purplegrain/apis/purple-grain-api/revisions/4bedbc1c784c?raw)
