Tasks

Create Task

Create a task or a record. An animal treatment (drench, vaccination, pour-on, jetting, injection) on a mob should be createTreatmentRecord (category: "drench" for a drench), which sets the producer from the property's owner and stores the products. Use this operation when you also need operator, record_notes, record_summary or tags, or when the asset is a paddock.

One asset per record. A treatment after the fact is status: completed, created_as: record, with drench.products set. A planned treatment is status: pending, created_as: task. Back-date completed_at with an Australian offset (2025-12-23T09:00:00+11:00 is stored as 2025-12-22T22:00:00Z). Use 09:00 local when only a date is known. AEDT is +11:00 (first Sunday of October to first Sunday of April); AEST is +10:00.

Producer. For a property owned by a business, set producer to that organization (type: organization). Omitting it returns 403 Forbidden, detail "Unauthorized", with source.pointer /request/headers/authorization. That is a missing producer, not a bad token. A 403 whose code is insufficient_access is a real access refusal: show its detail and do not retry.

Broadcasting is paused for agents. A request from an API or MCP client whose body names broadcast or share_scope — true or false — is refused with 403 and nothing is written; leave both out. First-party web and mobile requests are unaffected.

PurpleGrain AI record. The composer's AI mode creates a task with operation_type: ai, capture_source: voice or typed, status: completed, created_as: record, description set to the farmer's own words, and no typed child. The asset (a mob or paddock) is optional; without one, send the farm relationship so the record still belongs to a property (you must be able to edit that property). Photos go on afterwards with POST /tasks/{task_id}/images. The formatter (AiFormatJob) picks the record up after about 30 seconds, reads the words, the photos and, unless the organisation switched ai_format_enabled off, the farm's records, then writes the typed child, links the asset and sets ai_format_done_at. It never invents a batch, dose, expiry, WHP or ESI: a value the words and photos do not support is listed in ai_format_meta.unconfirmed. A record it cannot place keeps no asset and lists the candidates in ai_format_meta.candidates; attach one with updateTask (below). Not a way to create tasks with AI: the paused POST /tasks/ai is unchanged.

PurpleGrain AI records are first-party. The formatter is for a farmer's untyped words. An MCP client already knows what the record is, so a request from one whose body sets operation_type: ai is refused with 403 and nothing is written; write the typed record instead (treatment, husbandry, spray, fertiliser, sowing or fieldwork, or the matching create*Record operation) with capture_source: agent. API keys and the app's own requests are unaffected.

Photos. A file on disk: call createImageUpload, run the returned curl_example from the shell, then pass image_upload_ids. Never base64-encode a local photo into a tool call. A public http(s) URL: pass image_urls. Only a tiny generated image (under about 100 KB decoded) uses image_base64s. One upload can be attached to several records until it expires. On update, image_mode defaults to append (add to the existing photos); replace swaps them all out; remove_image_ids deletes specific ones. If any image fails, nothing is saved. An Idempotency-Key header makes a retried create return the original task. The attaching call still needs confirm: true.

The MCP tool is refused until it is called again with confirm: true. If the call errors or times out, read the asset's records (listTasks with asset_id) before retrying.

Example, organization-owned farm (application/vnd.api+json):

{
  "data": {
    "type": "task",
    "attributes": {
      "operation_type": "drench",
      "status": "completed",
      "created_as": "record",
      "capture_source": "agent",
      "completed_at": "2025-12-23T09:00:00+11:00",
      "operator": "AH",
      "description": "Drench rams",
      "record_summary": "Drenched Rams (11 hd): Startect 20 mL/hd. WHP until 6 Jan 2026, ESI until 20 Jan 2026",
      "record_notes": "Expiry: not recorded. Route: oral.",
      "tags": ["drench", "startect", "whp-until-2026-01-06", "esi-until-2026-01-20"],
      "drench": {
        "head": 11,
        "products": [
          { "name": "Startect", "batch": "728661", "dose": "20 mL per head", "whp_days": 14, "esi_days": 28 }
        ]
      }
    },
    "relationships": {
      "asset": { "data": { "type": "mob", "id": "<mob id>" } },
      "farm": { "data": { "type": "farm", "id": "<farm id>" } },
      "producer": { "data": { "type": "organization", "id": "<owning organization id>" } }
    }
  }
}
post/tasks

Request

  • Base URL: https://api.purplegrain.com/api/v1
  • URL: https://api.purplegrain.com/api/v1/tasks
  • Auth: HTTP bearer

Query parameters

includestring
Example:producer,provider,service

Comma-separated snake_case relationship paths to embed (JSON:API included array, or inlined for application/json). Never embedded by default; unknown paths ignored; dot notation selects children; max 10 paths. Allowed paths: producer, provider, category, place, place.location, service, service.owner, service.category, service.city, service.place, service.location, farm, parent, children, asset.

Headers

Idempotency-Keystring

Optional. Send the same value when retrying a create after a 502 or 504. The same user, path and key returns the original result instead of writing a second one. The key is kept for 24 hours.

Request body

Response

Success. When the include query parameter is used, the response may contain an included array (JSON:API) or inlined related resources (application/json).

Example response

{
  "data": {
    "type": "task"
  }
}

Changes

No recorded changes to this operation across all 2 revisions of this API.