Reference for the JSON returned by FarmAsk's records-with-AI data export endpoint. Last updated: 2026-06-13. Schema version 1.1.
This page describes the structure of the JSON file you receive when you request an export of your Farm Notebook data. The format is documented so you can use the data with other tools, reload it into your own systems, or hand it to a vet, agronomist, or accountant.
Under GDPR Article 20 (right to portability), you can request a copy of the data we hold about you in a structured, commonly used, machine-readable format. This export is that format for your records data.
Note: this export covers the records-with-AI feature only — uploaded documents, extracted data, field references, and your farm context summary. For a full export of your account (chat history, profile, etc.) call POST /user/data-export separately. The two exports are intentionally separate; you may request either or both.
Authenticated POST /farm/data/export kicks off an asynchronous job and returns a job_id. Poll GET /farm/data/export/:job_id until the job's status is "ready", then download the JSON from the download_url.
{
"schema_version": "1.1",
"generated_at": "2026-05-08T14:32:00.000Z",
"format_documentation": "https://legal.farmask.ai/records-export-schema",
"user_id": "uuid",
"disclosure": { ... },
"farm_documents": [ ... ],
"farm_document_field_refs": [ ... ],
"user_farm_context": { ... },
"activity_log_entries": [ ... ]
}
| Key | Type | Description |
|---|---|---|
schema_version | string | Schema version this export uses. "1.0" is the initial stable version. We bump the minor version (1.1, 1.2, ...) for additive changes that don't break existing readers, and the major version (2.0) for breaking changes. |
generated_at | ISO 8601 UTC string | The moment the export was generated. |
format_documentation | URL | Link back to this page so a future reader knows where to look for schema details. |
user_id | UUID string | Your FarmAsk user identifier. |
disclosure | object | Notes about scope and third-party processors. See below. |
farm_documents | array | Every document you've uploaded to Farm Notebook, including soft-deleted ones (so the export is exhaustive). See document fields below. |
farm_document_field_refs | array | The cross-document field index — one row per (document, field) reference. Lets you reconstruct "every doc that mentioned Bottom 40" outside of FarmAsk. |
user_farm_context | object | Your current Farm Notebook prose summary plus the denormalised aggregates (field count, total area, document count). See below. |
activity_log_entries | array | Every task you logged by text or voice (the activity log), including soft-deleted ones (so the export is exhaustive). See activity-entry fields below. Added in schema 1.1. |
farm_documents[] — per-document fields| Key | Type | Description |
|---|---|---|
id | UUID | Document identifier (stable; survives across exports). |
conversation_id / message_id | UUID, nullable | The chat conversation/message the document was attached to, if any. |
filename | string | Original filename you uploaded. |
mime_type | string | IANA MIME type (e.g. image/png, application/pdf). |
media_type | string | Coarse category: image, pdf, text, document. |
file_size_bytes | integer | Original file size. |
document_type | string, nullable | One of farm_map, cropping_report, soil_test, forage_analysis, spray_plan, scheme_agreement, vet_plan, invoice, field_list, other. Null until extraction completes. |
detection_confidence | float, nullable | Classification confidence 0.0–1.0. |
extraction_language | ISO 639-1 string, nullable | Detected primary language of the document. |
extraction_status | string | One of pending, processing, complete, failed. |
extraction_summary | string, nullable | Conversational reply describing what we extracted. |
extracted_data | object, nullable | Structured extraction. Shape varies by document_type — see per-type extraction schemas below. Immutable — never edited. |
verification_state | string | unverified or verified. |
pending_clarifications | object, nullable | Workflow-mutable subset of clarifying questions still awaiting answers. |
user_edited | boolean | True if you've added notes or marked the doc verified. |
user_notes | string, nullable | Free-text note you added. |
created_at / updated_at / deleted_at | ISO 8601, nullable | Timestamps. deleted_at is null on active docs; populated on docs you've deleted (export includes deleted-but-not-yet-purged docs for completeness). |
media_url | URL string | Pre-signed URL to download the original uploaded file. Valid for 24 hours from the export's generated_at. Note on HEIC/HEIF: if the original was uploaded from an iPhone (default HEIC encoding), browsers other than Safari may not render it natively — the data is portable but you may need a HEIC-aware tool to view it (Preview on macOS, Photos on iOS, or a third-party converter on other platforms). |
media_url_expires_at | ISO 8601 | Exact expiry of the media_url. After this moment you must request a new export to get fresh URLs. |
extracted_data schemasThe extracted_data field on each document follows a schema specific to that document's document_type. Skeletons below show the shape; absent fields mean the model couldn't find a value (we omit rather than fabricate). Every schema includes a clarifications array (questions the model flagged at extraction time — these are immutable; the active workflow subset lives in pending_clarifications at the document level) and an additional_notes string for content that didn't fit the structured fields.
Locked rules across all types: original language preserved verbatim; original units preserved verbatim (acres stays acres, hectares stays hectares — no conversion); original date and currency conventions retained.
farm_mapAny map of farm fields, hand-drawn or printed.
{
"fields": [
{"name": "...", "area_value": 0, "area_unit": "...", "field_type": "...", "confidence": "high|medium|low", "notes": "..."}
],
"total_area_value": 0,
"total_area_unit": "...",
"date_or_season": "...",
"farm_name": "...",
"annotations": [{"type": "...", "description": "..."}],
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
cropping_reportPlanting plan or rotation schedule. field_block appears when rotation is at block level rather than field level.
{
"crops": [
{"crop": "...", "variety": "...", "field": "...", "area_value": 0, "area_unit": "...", "field_block": "..."}
],
"total_cropped_area_value": 0,
"total_cropped_area_unit": "...",
"season": "...",
"advisor": "...",
"farm_name": "...",
"report_date": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
soil_testSoil analysis from a lab. indices are unit-less (e.g. UK's index 0–9 system); values carry the underlying mg/l measurements. recommendations are the lab's input recommendations in the units they used.
{
"fields_tested": [
{"field_name": "...", "ph": 0, "indices": {"p": 0, "k": 0, "mg": 0}, "values": {"p_mg_per_l": 0, "k_mg_per_l": 0, "mg_mg_per_l": 0}, "organic_matter_pct": 0, "recommendations": {"p2o5_kg_per_ha": 0, "k2o_kg_per_ha": 0, "mgo_kg_per_ha": 0, "lime_t_per_ha": 0}}
],
"lab": "...",
"report_date": "...",
"report_reference": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
forage_analysisHaylage/silage/feed nutritional analysis. fields_or_batch identifies the source — sometimes a field name, sometimes a batch ID.
{
"material_type": "...",
"fields_or_batch": "...",
"results": {"dry_matter_pct": 0, "crude_protein_pct": 0, "d_value_pct": 0, "me_mj_per_kg": 0, "sugars_pct": 0, "ph": 0, "ndf_pct": 0, "adf_pct": 0, "ash_pct": 0},
"lab": "...",
"report_date": "...",
"report_reference": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
spray_planPesticide/herbicide application plan or record. fields[] describes the planned scope; products[] describes what's being applied; applications[] records actual events with weather conditions.
{
"fields": [
{"name": "...", "crop": "...", "variety": "...", "area_value": 0, "area_unit": "...", "growth_stage": "..."}
],
"products": [
{"name": "...", "active_ingredient": "...", "rate_value": 0, "rate_unit": "...", "total_value": 0, "total_unit": "...", "reason": "..."}
],
"plan_date": "...",
"earliest_harvest_date": "...",
"advisor": "...",
"applications": [
{"field": "...", "date": "...", "operator": "...", "weather": {"wind_speed": "...", "wind_direction": "...", "temp": "...", "humidity": "..."}}
],
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
scheme_agreementGovernment agri-environment or subsidy scheme document. parcel_id is the formal identifier (e.g. RPA "OS Field 12345"); code is the scheme action code (e.g. SFI's "AHL1"); description is free text.
{
"scheme_name": "...",
"agreement_reference": "...",
"parcels": [
{"parcel_id": "...", "code": "...", "description": "...", "area_value": 0, "area_unit": "...", "length_value": 0, "length_unit": "...", "start_date": "...", "end_date": "..."}
],
"total_area_value": 0,
"total_area_unit": "...",
"agreement_status": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
vet_planLivestock health plan or veterinary document. monthly_actions[] structures the year by management/vaccination/parasites/disease-watch.
{
"livestock_type": "...",
"stock_count": 0,
"monthly_actions": [
{"month": "...", "management": [], "vaccinations": [], "parasites_treatments": [], "disease_watch": []}
],
"vet_practice": "...",
"plan_date": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
invoiceContractor or supplier invoice. operations[] is the line-item list; currency uses the invoice's original currency code (e.g. "GBP", "EUR", "USD").
{
"supplier": "...",
"invoice_number": "...",
"invoice_date": "...",
"operations": [
{"operation_type": "...", "fields": [], "rate_value": 0, "rate_unit": "...", "total_value": 0, "total_unit": "...", "amount": 0}
],
"subtotal": 0,
"vat": 0,
"total": 0,
"currency": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
field_listTyped/written list of fields with sizes. Simpler than farm_map — no annotations, no farm-level metadata.
{
"fields": [
{"name": "...", "area_value": 0, "area_unit": "...", "field_type": "...", "notes": "..."}
],
"total_area_value": 0,
"total_area_unit": "...",
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
otherCatch-all for any farm-related document the model couldn't classify into one of the nine types above. extracted_items[] captures arbitrary structured data; fields_mentioned[] and dates_mentioned[] aid cross-document indexing.
{
"summary": "...",
"extracted_items": [
{"category": "...", "value": "...", "context": "..."}
],
"fields_mentioned": [],
"dates_mentioned": [],
"clarifications": [{"question": "..."}],
"additional_notes": "..."
}
farm_document_field_refs[] — per-(doc, field) rowThe field reference index built across your documents. Lets you query "every document that mentions Bottom 40" without re-reading every extracted_data object.
| Key | Type | Description |
|---|---|---|
document_id | UUID | The doc this reference came from. Joins back to farm_documents[].id. |
field_name | string | Original field name as it appeared in your document (preserved casing/spelling). |
field_name_normalized | string | Lowercase, trimmed, accent-folded form. Use this as the join key when grouping references across documents. |
area_value / area_unit | float / string, both nullable | Field area as it appeared in the source. Units NOT converted — acres stays acres, hectares stays hectares. |
context | object | What the source document said about this field (crop, growth stage, scheme, etc.). Shape varies by source document_type. |
user_farm_context — the prose summary| Key | Type | Description |
|---|---|---|
context_summary | string, nullable | One-paragraph summary an AI advisor uses as context. Regenerated after every doc change. |
field_count | integer | Distinct fields detected across your documents. |
total_area_value / total_area_unit | float / string, nullable | Sum of areas in the dominant unit. We do NOT convert across units — if your docs mix acres and hectares, this is the sum in whichever unit appears most often, with mixed-unit fields excluded. |
document_count | integer | Active (non-deleted) documents. |
last_refreshed_at | ISO 8601, nullable | When this summary was last regenerated. |
activity_log_entries[] — per-entry fields (schema 1.1)Each entry is one task you logged by text or voice. The original wording and language are preserved verbatim; we never translate or unit-convert. Voice audio is not retained — it is deleted immediately after transcription, so only the transcript text persists here.
| Key | Type | Description |
|---|---|---|
id | UUID | The entry identifier. |
source | string | "text" or "voice" — how you logged it. |
raw_text | string | Your entry exactly as typed, or the verbatim transcript of your voice note (original language preserved). |
edited_text | string, nullable | Your correction to the text, if you edited the entry; otherwise null. The original raw_text is always retained. |
language | string, nullable | Detected/declared language tag, when known. |
occurred_on | date (YYYY-MM-DD) | The date of the activity, resolved against your local date. |
occurred_on_inferred | boolean | true if the date was assumed (e.g. from "today"/"yesterday" or defaulted to the capture date) rather than an explicit calendar date you stated. |
extracted_records | object | The structured records[] read from your entry — same universal {subject, attribute, value, unit?, canonical_attribute, confidence} shape as documents. Original language + units preserved verbatim. |
entry_class | string | "diary" (saved as-is) or "needs_confirm" (flagged for you to verify because it carried a consequential value — e.g. a medicine dose, a death — or a financial figure). |
confirm_reasons | object, nullable | When needs_confirm, the families that triggered it (e.g. { "families": ["dosing"] }); otherwise null. |
verification_state | string | "confirmed" or "pending". |
confirmed_at | ISO 8601, nullable | When you confirmed a pending entry. |
created_at / updated_at | ISO 8601 | When the entry was created / last changed. |
deleted_at | ISO 8601, nullable | Set when you deleted the entry. Soft-deleted entries are included in the export (exhaustiveness) and carry this timestamp so you can filter them. |
schema_version accordingly.generated_at. After that, request a new export. The export JSON file itself is also auto-deleted after 24 hours.user_farm_context.context_summary may briefly trail the document data — re-export after ~15 seconds for a fully consistent snapshot. The raw farm_documents[] and farm_document_field_refs[] are always fresh; only the prose paragraph lags during a refresh cascade.{
"schema_version": "1.1",
"generated_at": "2026-05-08T14:32:00.000Z",
"format_documentation": "https://legal.farmask.ai/records-export-schema",
"user_id": "0d5f...",
"disclosure": {
"notice": "This export contains your records-with-AI data...",
"third_party_processors": [
{ "name": "Anthropic (Claude)", "purpose": "Document classification + extraction + summary" },
{ "name": "OpenAI (Whisper)", "purpose": "Voice transcription for voice-logged activity entries" },
{ "name": "Supabase", "purpose": "Database + file storage hosting" }
]
},
"farm_documents": [
{
"id": "1a99...",
"filename": "field-list.png",
"document_type": "field_list",
"extraction_status": "complete",
"extracted_data": { "fields": [{ "name": "North Field", "area_value": 12.5, "area_unit": "acres" }] },
"media_url": "https://<supabase>/storage/v1/object/sign/farm-documents/...",
"media_url_expires_at": "2026-05-09T14:32:00.000Z",
...
}
],
"farm_document_field_refs": [
{ "document_id": "1a99...", "field_name": "North Field", "field_name_normalized": "north field", "area_value": 12.5, "area_unit": "acres", "context": {...} }
],
"user_farm_context": {
"context_summary": "The farm comprises 5 fields totalling 67.2 acres...",
"field_count": 5,
"total_area_value": 67.2,
"total_area_unit": "acres",
"document_count": 1,
"last_refreshed_at": "2026-05-08T14:31:55.000Z"
},
"activity_log_entries": [
{
"id": "7c3b...",
"source": "voice",
"raw_text": "Dosed pen 4, 40 ewes, Zolvix 2ml",
"edited_text": null,
"language": null,
"occurred_on": "2026-06-09",
"occurred_on_inferred": true,
"extracted_records": { "records": [
{ "subject": "Zolvix", "attribute": "product_name", "value": "Zolvix", "canonical_attribute": "product_name", "confidence": "high" },
{ "subject": "Zolvix", "attribute": "dose_value", "value": 2, "unit": "ml", "canonical_attribute": "dose_value", "confidence": "high" }
], "clarifications": [], "additional_notes": "" },
"entry_class": "needs_confirm",
"confirm_reasons": { "families": ["dosing"] },
"verification_state": "pending",
"confirmed_at": null,
"created_at": "2026-06-09T08:14:00.000Z",
"updated_at": "2026-06-09T08:14:00.000Z",
"deleted_at": null
}
]
}
Email support@farmask.ai if a field is unclear or you have suggestions for additional structure. We treat schema documentation as a contract with users invoking their portability rights.