A Farm is a company's physical farm site — the top level of the Farm Management hierarchy. Fields belong to a Farm, and everything else (Cultivations, Fertilization) chains down from there.
This page covers only what's specific to Farms. For the base URL, authentication, the response envelope, pagination, sharing, the foreign-key _id convention, and soft delete, see Farm Management Overview.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /farm/ | List farms |
| POST | /farm/ | Create a farm (single object or bulk array) |
| GET | /farm/FARM_ID/ | Retrieve a single farm |
| PUT | /farm/FARM_ID/ | Replace a farm |
| PATCH | /farm/FARM_ID/ | Partially update a farm |
| DELETE | /farm/FARM_ID/ | Soft delete a farm |
| POST | /farm/FARM_ID/pin/ | Pin the farm for the current user — see Pinning |
| DELETE | /farm/FARM_ID/pin/ | Unpin it |
| POST | /farm/pins/reorder/ | Reorder the current user's pinned farms |
Auth
Requires a Bearer token — see Farm Management Overview for how to send one.
Each action also requires a dynamic permission on top of the token — with one exception, the pin endpoints, which need none (see Pinning):
| Action | Required permission |
|---|---|
| List / Retrieve | farm.view |
| Create | farm.create |
| Update / Partial update | farm.edit |
| Delete | farm.delete |
A request with a valid token but missing the required permission gets an HTTP 403 with the structured body described in Farm Management Overview.
List filters
GET /farm/ accepts these query parameters:
| Filter | Type | Matches |
|---|---|---|
name | string | Case-insensitive partial match (icontains) |
address | string | Case-insensitive partial match (icontains) |
main | boolean | Exact match — whether the farm is flagged as the company's primary farm |
pinned | boolean | true returns only the farms you have pinned, false only the rest — see Pinning |
company | integer | Exact match on company (generic filter) |
created_by | integer | Exact match on the creating user (generic filter) |
created_at | date range | Generic created-at range filter |
Create / update fields
| Field | Type | Required | Notes |
|---|---|---|---|
name | string, max 255 | Yes | |
lat | decimal | No | |
lng | decimal | No | |
address | text | No | |
note | text | No | |
main | boolean | No | Marks this as the company's primary farm |
Don't send
company,company_id, orcreated_by— they're set automatically from your authenticated user and token, and aren't accepted as write input.
Response fields
Beyond the fields above, a Farm response also includes:
| Field | Notes |
|---|---|
total_fields | Count of this farm's non-deleted fields |
is_pinned | Whether you have pinned this farm. Per-user — your colleagues see their own value |
pin_priority | Your manual rank for this farm, 0 first. null when it isn't pinned |
is_first | true on the very first farm ever created for your company. Set once by the server and never moves, even if that farm is later deleted. Read-only |
created_at | Set on creation |
updated_at | Set on every update |
company | Nested, read-only — see Farm Management Overview on the _id-for-write convention |
created_by | Nested, read-only — no created_by_id to write |
Every new company is created with a starter "Default Farm" already in place, so that
is normally the record carryingis_first: true— not the first one a user creates by hand.
If you're usingis_firstto drive an onboarding or milestone moment, check the record's
name/created_bytoo rather than treating the flag on its own as "the user made their
first farm".
Pinning
Each user can pin farms so they surface at the top of their own list, and drag the pinned
cards into whatever order they want. Pins are per-user: pinning a farm changes nothing
for your colleagues, even though you both see the same farms.
| Method | Path | Body | Purpose |
|---|---|---|---|
| POST | /farm/FARM_ID/pin/ | — | Pin the farm. It goes to the top (pin_priority: 0) and everything else shifts down |
| DELETE | /farm/FARM_ID/pin/ | — | Unpin it. The remaining pins close up so the ranks stay 0,1,2,… |
| POST | /farm/pins/reorder/ | {"ids": [12, 7, 30]} | Persist a drag-and-drop reorder |
POST /farm/FARM_ID/pin/ returns {"id": 12, "is_pinned": true, "pin_priority": 0}.
Pinning something already pinned is not an error — it just moves back to the top.
DELETE returns 204, or 404 if the farm wasn't pinned.
Unlike every other action on this page, the pin endpoints need no permission. Pinning is a
per-user display preference, not an operation on company data, so it isn't part of the
dynamic-permission system — if the user can see the farm, they can pin it. Don't gate your pin
button on a permission check.This doesn't widen visibility: pinning resolves the farm through the same company scoping as
everything else, so another company's farm is still a404.
Reordering
Send the complete ordered list of pinned farm ids, top first. The server renumbers
pin_priority to 0,1,2,… to match and echoes back the resulting order:
{ "ids": [30, 12, 7] }- Any id you leave out keeps its relative order and is appended after the ones you sent —
reordering never unpins anything. 400if an id isn't currently pinned by you, isn't one of your company's farms, or the
list contains duplicates. The whole request is rejected; nothing is partially applied.
pin_priorityis yours to define — it exists so a drag-and-drop list can be persisted. It
is only meaningful among pinned farms; unpinned farms always havepin_priority: null.
Showing pinned farms first
Pin order is opt-in, so nothing changes for existing integrations. Add
?prioritize=true to sort pinned farms to the top in your chosen order, with everything
else following in the usual newest-first order:
GET /farm/?prioritize=true
Without it, GET /farm/ returns exactly the order it always has. is_pinned and
pin_priority are present on every farm response either way, so you can render the pin
icon without asking for the reordering.
Bulk create
POST /farm/ also accepts a JSON array of farm objects instead of a single object, to create several farms in one request. See Farm Management Overview for how Farms' bulk-error status code (400, for both single and bulk-array validation failures) differs from Fields' and Seasons' (402 for a bulk array with an invalid item).
Status codes
| Status | Trigger |
|---|---|
| 200 | List, retrieve, or update succeeded. |
| 201 | Create succeeded (single object or bulk array). |
| 204 | Delete succeeded (soft delete; no response body). |
| 400 | Validation failure — single object or bulk array. |
| 403 | Missing farm.view / farm.create / farm.edit / farm.delete permission. |
| 404 | Farm not found (wrong FARM_ID, wrong company, or already deleted). |
Create request
curl -X POST https://backend.spacenus.de/api/v1.2/farm/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "North Ridge Farm",
"lat": "52.5200",
"lng": "13.4050",
"address": "Musterstrasse 1, 12345 Berlin",
"note": "Primary grain operation",
"main": true
}'Response:
{
"status": "success",
"message": "Farm created successfully.",
"data": {
"id": 101,
"name": "North Ridge Farm",
"lat": "52.5200",
"lng": "13.4050",
"address": "Musterstrasse 1, 12345 Berlin",
"note": "Primary grain operation",
"main": true,
"total_fields": 0,
"company": {
"id": 7,
"name": "Musterhof GmbH"
},
"created_by": {
"id": 42,
"name": "Jane Doe"
},
"created_at": "2026-08-19T10:15:00Z",
"updated_at": "2026-08-19T10:15:00Z"
}
}