openapi: 3.0.3 info: title: 'farmOS JSON: Assets API' description: 'The farmOS JSON:API provides access to farm assets, logs, plans, and records. It follows the JSON:API specification (https://jsonapi.org/) with UUID-based resource identifiers. The root endpoint at /api returns server metadata and available resource types. Resource endpoints follow the pattern /api/[entity-type]/[bundle]. farmOS is an open-source farm management and record-keeping system built on Drupal. It supports self-hosted deployments and managed hosting via Farmier. ' version: 2.x contact: name: farmOS Community url: https://farmos.org/community/ license: name: GNU General Public License v2.0 url: https://github.com/farmOS/farmOS/blob/main/LICENSE.txt termsOfService: https://farmos.org/ servers: - url: https://{farmOS-host}/api description: Self-hosted farmOS instance variables: farmOS-host: default: example.farmos.net description: The hostname of your farmOS instance (self-hosted or Farmier-managed) security: - oauth2AuthorizationCode: - farm_manager - oauth2ClientCredentials: - farm_manager tags: - name: Assets description: Physical or logical farm assets (land, animals, equipment, plants, etc.) paths: /asset/animal: get: operationId: listAnimalAssets summary: List animal assets description: Returns a collection of animal assets. tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of animal assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createAnimalAsset summary: Create an animal asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Animal asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/animal/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getAnimalAsset summary: Get an animal asset tags: - Assets responses: '200': description: An animal asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateAnimalAsset summary: Update an animal asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated animal asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteAnimalAsset summary: Delete an animal asset tags: - Assets responses: '204': description: Animal asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/land: get: operationId: listLandAssets summary: List land assets description: Returns a collection of land assets (fields, beds, paddocks, etc.). tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of land assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createLandAsset summary: Create a land asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Land asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/land/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getLandAsset summary: Get a land asset tags: - Assets responses: '200': description: A land asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateLandAsset summary: Update a land asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated land asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteLandAsset summary: Delete a land asset tags: - Assets responses: '204': description: Land asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/plant: get: operationId: listPlantAssets summary: List plant assets tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of plant assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createPlantAsset summary: Create a plant asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Plant asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/plant/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getPlantAsset summary: Get a plant asset tags: - Assets responses: '200': description: A plant asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updatePlantAsset summary: Update a plant asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated plant asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deletePlantAsset summary: Delete a plant asset tags: - Assets responses: '204': description: Plant asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/equipment: get: operationId: listEquipmentAssets summary: List equipment assets tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of equipment assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createEquipmentAsset summary: Create an equipment asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Equipment asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/equipment/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getEquipmentAsset summary: Get an equipment asset tags: - Assets responses: '200': description: An equipment asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateEquipmentAsset summary: Update an equipment asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated equipment asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteEquipmentAsset summary: Delete an equipment asset tags: - Assets responses: '204': description: Equipment asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/structure: get: operationId: listStructureAssets summary: List structure assets tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of structure assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createStructureAsset summary: Create a structure asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Structure asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/structure/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getStructureAsset summary: Get a structure asset tags: - Assets responses: '200': description: A structure asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateStructureAsset summary: Update a structure asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated structure asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteStructureAsset summary: Delete a structure asset tags: - Assets responses: '204': description: Structure asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/sensor: get: operationId: listSensorAssets summary: List sensor assets tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of sensor assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createSensorAsset summary: Create a sensor asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Sensor asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/sensor/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getSensorAsset summary: Get a sensor asset tags: - Assets responses: '200': description: A sensor asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateSensorAsset summary: Update a sensor asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated sensor asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteSensorAsset summary: Delete a sensor asset tags: - Assets responses: '204': description: Sensor asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /asset/group: get: operationId: listGroupAssets summary: List group assets tags: - Assets parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageOffset' - $ref: '#/components/parameters/FilterField' - $ref: '#/components/parameters/SortField' - $ref: '#/components/parameters/IncludeRelated' responses: '200': description: A collection of group assets content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetCollection' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createGroupAsset summary: Create a group asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '201': description: Group asset created content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity' /asset/group/{id}: parameters: - $ref: '#/components/parameters/ResourceId' get: operationId: getGroupAsset summary: Get a group asset tags: - Assets responses: '200': description: A group asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: updateGroupAsset summary: Update a group asset tags: - Assets requestBody: required: true content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetRequest' responses: '200': description: Updated group asset content: application/vnd.api+json: schema: $ref: '#/components/schemas/AssetResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteGroupAsset summary: Delete a group asset tags: - Assets responses: '204': description: Group asset deleted '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' components: schemas: AssetRequest: type: object required: - data properties: data: $ref: '#/components/schemas/AssetData' JsonApiError: type: object properties: errors: type: array items: type: object properties: status: type: string title: type: string detail: type: string source: type: object properties: pointer: type: string AssetCollection: type: object properties: data: type: array items: $ref: '#/components/schemas/AssetData' included: type: array items: type: object links: type: object properties: self: type: string format: uri next: type: string format: uri prev: type: string format: uri meta: type: object properties: count: type: integer description: Total number of matching resources JsonApiRelationship: type: object properties: data: oneOf: - $ref: '#/components/schemas/JsonApiRelationshipData' - type: array items: $ref: '#/components/schemas/JsonApiRelationshipData' - nullable: true type: object maxProperties: 0 links: $ref: '#/components/schemas/JsonApiLinks' AssetRelationships: type: object description: Common relationships shared by all asset types properties: parent: $ref: '#/components/schemas/JsonApiRelationship' location: $ref: '#/components/schemas/JsonApiRelationship' image: $ref: '#/components/schemas/JsonApiRelationship' file: $ref: '#/components/schemas/JsonApiRelationship' AssetData: type: object required: - type - attributes properties: type: type: string description: JSON:API resource type (e.g., asset--animal, asset--land) example: asset--animal id: type: string format: uuid readOnly: true attributes: $ref: '#/components/schemas/AssetAttributes' relationships: $ref: '#/components/schemas/AssetRelationships' links: $ref: '#/components/schemas/JsonApiLinks' JsonApiLinks: type: object properties: self: type: string format: uri related: type: string format: uri JsonApiRelationshipData: type: object properties: type: type: string id: type: string format: uuid AssetResponse: type: object properties: data: $ref: '#/components/schemas/AssetData' included: type: array items: type: object links: $ref: '#/components/schemas/JsonApiLinks' AssetAttributes: type: object description: Common attributes shared by all asset types properties: drupal_internal__id: type: integer readOnly: true description: Internal Drupal integer ID (not for external use) name: type: string description: Asset name status: type: string enum: - active - archived description: Asset status (use archived to retire an asset) archived: type: boolean description: Whether the asset is archived (4.x and later) notes: type: object description: Free-form notes (rich text) properties: value: type: string format: type: string is_location: type: boolean description: Whether this asset can act as a location for other assets/logs is_fixed: type: boolean description: Whether the asset has a fixed geometry (does not move) intrinsic_geometry: type: string description: WKT geometry string for fixed-location assets geometry: type: string description: Computed current geometry (WKT) location: type: array description: Computed current location assets items: type: object nickname: type: array description: Alternative names/nicknames for the asset items: type: string id_tag: type: array description: Physical identification tags items: type: object properties: id: type: string type: type: string location: type: string image: type: array description: Attached images items: type: object file: type: array description: Attached files items: type: object created: type: integer description: Unix timestamp when the record was created readOnly: true changed: type: integer description: Unix timestamp when the record was last modified readOnly: true parameters: FilterField: name: filter[field] in: query description: 'JSON:API filter parameter. Use dot notation for nested fields. Example: filter[status]=pending or filter[timestamp][value]=1234567890&filter[timestamp][operator]=>= ' schema: type: string PageSize: name: page[limit] in: query description: Number of results per page schema: type: integer minimum: 1 maximum: 50 default: 50 IncludeRelated: name: include in: query description: 'Comma-separated list of related resources to include in the response. Example: include=asset,quantity ' schema: type: string SortField: name: sort in: query description: 'Comma-separated list of fields to sort by. Prefix with - for descending. Example: sort=-timestamp,name ' schema: type: string PageOffset: name: page[offset] in: query description: Offset for pagination schema: type: integer minimum: 0 default: 0 ResourceId: name: id in: path required: true description: UUID of the resource schema: type: string format: uuid example: 3f1c2b4a-5d6e-7890-abcd-ef1234567890 responses: NotFound: description: Resource not found content: application/vnd.api+json: schema: $ref: '#/components/schemas/JsonApiError' UnprocessableEntity: description: Validation error content: application/vnd.api+json: schema: $ref: '#/components/schemas/JsonApiError' Unauthorized: description: Authentication required or token expired content: application/vnd.api+json: schema: $ref: '#/components/schemas/JsonApiError' securitySchemes: oauth2AuthorizationCode: type: oauth2 description: 'OAuth2 Authorization Code grant for third-party integrations. Users authorize the client application to access their farmOS data. ' flows: authorizationCode: authorizationUrl: /oauth/authorize tokenUrl: /oauth/token scopes: farm_manager: Full management access to the farm farm_worker: Worker-level access to farm records farm_viewer: Read-only access to farm records oauth2ClientCredentials: type: oauth2 description: 'OAuth2 Client Credentials grant for machine-to-machine authentication. Used when no user account is required. ' flows: clientCredentials: tokenUrl: /oauth/token scopes: farm_manager: Full management access to the farm farm_worker: Worker-level access to farm records farm_viewer: Read-only access to farm records externalDocs: description: farmOS API Documentation url: https://farmos.org/development/api/