openapi: 3.2.0 info: description: emem is shared memory for AI agents working together in the real world. license: name: Apache-2.0 title: emem Field Boundaries API version: 2.4.0 x-emem-surface-asymmetry: memory_notes: MCP only reach_them_at: POST /mcp, method tools/call read_side_is_here: - /v1/memory/search - /v1/memory/sse - /memories/{path} tools: - emem_memory_create - emem_memory_view - emem_memory_delete - emem_memory_rename - emem_memory_str_replace - emem_memory_supersede why_not_here: These write the agent correspondence plane, which is prose and untrusted-by-declaration. It is deliberately not part of the REST fact surface, and the two planes are kept apart rather than merged for convenience. servers: - description: Hosted instance (HTTPS-only) url: https://emem.dev tags: - name: Field Boundaries paths: /v1/field_boundaries: post: description: 'Per-field agricultural-boundary polygons from the Fields of The World global product (~3.17B fields, 241 countries, 10 m resolution, CC-BY-4.0). Returns a GeoJSON FeatureCollection with the polygon geometries, FIBOA-compatible properties, and a planar `area_m2` per field, plus provenance (source CID, provider URL, license, attribution). When to use: Call when the user asks about farms, fields, parcels, croplands, plots, or agricultural boundaries inside a region, anywhere the OSM/Nominatim boundary alone is too coarse (the OSM polygon for a farm is its estate envelope; this returns the individual field polygons inside). Pass `place` (free-text) or `polygon_bbox`. For farms wider than ~10 km², split the bbox: the fetcher caps each call at 16 covering tiles. The receipt quotes `license: CC-BY-4.0` and `attribution: Fields of The World / Taylor Geospatial Institute`, surface both with any rendered map. For a one-shot "facts at every cell inside the farm PLUS the field polygons", call `emem_recall_polygon` with `include: ["ftw_fields"]` instead.' operationId: emem_field_boundaries requestBody: content: application/json: schema: properties: clean: default: false description: 'resolve overlaps and drop nested duplicate rings before returning; the response then carries a `synthesis` record (operator overlap_resolution@1, the vintage and source cid it ran on, overlap before and after in m2, what was dropped) on the envelope and on every feature. Gaps between parcels are left alone on purpose: on farmland they are bunds and tracks, not defects. Not a regularisation and not an infill of unmapped ground.' type: boolean max_features: description: cap on returned polygons; default 10000 type: integer place: description: one of place or polygon_bbox is required type: string polygon_bbox: description: OBJECT form only; see /v1/recall_polygon for why an array is refused. properties: max_lat: maximum: 90 minimum: -90 type: number max_lng: maximum: 180 minimum: -180 type: number min_lat: maximum: 90 minimum: -90 type: number min_lng: maximum: 180 minimum: -180 type: number required: - min_lat - max_lat - min_lng - max_lng type: object zoom: description: web-Mercator zoom; default min(14, archive max) type: integer type: object required: true responses: '200': content: application/json: schema: $ref: '#/components/schemas/FieldBoundariesResp' description: ok '400': content: application/json: schema: properties: details: type: object error: type: string type: object description: invalid argument; `details.code` names which rule refused default: content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' description: 'error, the emem.error.v1 envelope. Branch on the stable `code` (see GET /v1/errors), not the message. A malformed or missing-field request body returns `code: invalid_argument` with the offending field named in `message`.' summary: per-field agricultural-boundary polygons (Fields of The World, CC-BY-4.0) tags: - Field Boundaries components: schemas: Cost: description: 'Self-declared cost block on every receipt. Honest accounting: latencies are observed, freshness is the age of the stalest source cited (null when undatable, never 0 as a stand-in), `was_cached` is true when the hot cache served the read.' properties: credits: description: Conceptual cost units; 0 for L0/L1 read endpoints on the hosted responder. type: number latency_p50_ms: type: number latency_p99_ms: type: number source_freshness_s: description: 'Age of the STALEST source this response cites: now minus the earliest captured_at across the returned facts'' sources. null when nothing in the response carries a dated source, which is the honest answer for a primitive that reads no observation. Was a hardcoded 0 until 2026-08-05, so a 2021 DEM tile reported as 0 s old; a null here means unknown, never fresh.' type: - integer - 'null' was_cached: type: boolean type: object ErrorEnvelope: description: The `emem.error.v1` failure envelope returned by every endpoint on a 4xx/5xx. Branch on the stable `code` (not the human `message`). See GET /v1/errors for the full code catalog. properties: code: description: Stable machine-readable error code. One of the codes in GET /v1/errors. example: invalid_argument type: string details: description: Optional structured recovery hints; present on errors that ship machine-readable next-steps. type: object message: description: Human-readable detail. For invalid_argument this names the offending field (e.g. "missing field `q`"). type: string path: description: Request path that produced the error. example: /v1/ask type: string schema: const: emem.error.v1 type: string required: - code - message - schema type: object PubKey: description: Ed25519 32-byte public key, base32-nopad-lowercase encoded (52 chars). Returned in receipts and `/.well-known/emem.json`. example: 777er3yihgifqmv5hmc2wwmyszgddzderzhsx6rex4yoakwomvka type: string Cell64: description: 'cell64 wire form: four base-65,536 bigrams separated by dots, e.g. `defi.zb4d9.pefa.zf619`. Encoded resolution is ~9.55 m at the equator. Each bigram is either a CVCV quad, consonant `[bcdfghjklmnpqrstvwxyz]` followed by vowel `[aeiouAEIOU]` repeated twice, OR a synthetic 5-char `z[0-9a-f]{4}` slot used for the unused pad cells in the 65,536-entry alphabet. The regex pin matches `pattern` below byte-for-byte and is also surfaced under `Cell64Pattern` so agents can validate before sending.' example: defi.zb4d9.pefa.zf619 maxLength: 23 minLength: 19 pattern: ^(?:(?:[bcdfghjklmnpqrstvwxyz][aeiouAEIOU]){2}|z[0-9a-f]{4})(?:\.(?:(?:[bcdfghjklmnpqrstvwxyz][aeiouAEIOU]){2}|z[0-9a-f]{4})){3}$ type: string FieldBoundariesResp: description: Response of /v1/field_boundaries. `fields` is an array of per-field GeoJSON-Polygon features from Fields of The World (CC-BY-4.0). `attribution` and `license` must be surfaced with any rendered map. properties: attribution: example: Fields of The World / Taylor Geospatial Institute type: string fields: items: properties: area_ha: type: number confidence: type: number country: type: string geometry: description: GeoJSON Polygon. type: object type: object type: array license: example: CC-BY-4.0 type: string receipt: $ref: '#/components/schemas/Receipt' required: - fields - license - attribution type: object FactCid: description: 'Content id of a fact: base32-nopad-lowercase encoding of `blake3(canonical_cbor(fact))`, the FULL 32-byte digest with no truncation. Always 52 characters, alphabet `[a-z2-7]`. A cid of any other length is a damaged citation, not a shorter address: /v1/memory_token/resolve rejects it as `fact_cid_malformed_length` rather than guessing. Note that `entity_cid` and `bundle_cid` are NOT this shape; both truncate to 16 bytes (26 characters) and hash an identity anchor or a citation list rather than a complete body.' example: qtv2bco56qw4pmlohk56dotoxyl3atmnjpmzrijj2kazw2mj57oq maxLength: 52 minLength: 52 pattern: ^[a-z2-7]{52}$ type: string Receipt: description: 'Ed25519-signed receipt. The browser-side verifier at /verify reconstructs the preimage from the receipt fields alone, no callback to the issuer. **A receipt is byte-for-byte or nothing.** Current receipts carry `preimage_version: 2`, whose preimage binds request_id, served_at, primitive, cells, fact_cids AND, when present, the scope / as_of / edges / source_versions / field digests and the `merkle_proof` segment. Reshaping a receipt — dropping a field an SDK considers redundant, re-keying it, summarising it, round-tripping it through a lossy model — invalidates the signature BY DESIGN, and the result is indistinguishable on the wire from tampering. Store and forward the responder''s exact bytes. POST /v1/verify_receipt names which of the two it is where it can prove the difference (`reason: receipt_reshaped_after_signing` with a `failure_detail`). What is NOT signed: the caller''s `place`/`q` string, raw `lat`/`lng`, requested `bands[]`, requested `tslot`, and `intent` — a wrong-place geocode produces a valid signature for the wrong cell. Branch on /v1/locate `selected.is_high_confidence` before trusting place-anchored answers. Also: `fact_cid` is per-replica (signed_at differs across responders even for byte-identical upstream pixels); cross-replica join key is the tuple (cell, band, tslot). /v1/recall_polygon emits one independently signed receipt per cell under `by_cell..receipt`, `merged_facts[]` is convenience flattening and is NOT covered by an aggregate signature.' properties: cells: items: $ref: '#/components/schemas/Cell64' type: array cost: $ref: '#/components/schemas/Cost' fact_cids: items: $ref: '#/components/schemas/FactCid' type: array intent: description: Optional natural-language hint. Populated when served via /v1/intent. type: string merkle_proof: description: 'Inclusion proof for `fact_cids[0]` when persisted. Omitted from JSON when the cited facts pre-date the proof tree; under preimage_version 2 that absence is itself signed (an explicit ABSENT marker), so it is a statement rather than a gap. Do not strip this field: v2 binds it into the signature and removing it makes an authentic receipt report `signature_valid: false`.' properties: leaf_index: description: u32 leaf index in the canonical-sorted batch. type: integer path: description: Sibling hashes leaf→root. items: description: 32-byte sibling hash as a byte array items: type: integer type: array type: array root: description: The expected 32-byte batch root as a byte array. items: type: integer type: array version: description: 'Merkle hashing rule: 0 (omitted) = legacy unprefixed, 1 = RFC 6962-style prefixed.' type: integer required: - leaf_index - path - root type: object primitive: description: 'Namespaced wire form: `emem.recall`, `emem.find_similar`, `emem.verify`, …' type: string registry_cid: description: CID of the function registry version in force. type: string request_id: description: ULID generated per request. type: string responder: $ref: '#/components/schemas/PubKey' responder_key_epoch: description: u32 rotation counter; bumps when the operator rotates keys. type: integer responder_pubkey_b32: $ref: '#/components/schemas/PubKey' schema_cid: description: CID of the active CDDL profile. type: string served_at: description: ISO 8601 UTC, second precision. type: string signature: description: Ed25519 signature, 64 bytes base32-nopad-lowercase encoded. type: string source_versions: additionalProperties: type: string description: Per-source freshness map. type: object required: - request_id - served_at - primitive - cells - fact_cids - schema_cid - responder - responder_key_epoch - responder_pubkey_b32 - signature - registry_cid type: object