{"openapi":"3.1.0","info":{"title":"Origonex Public API","version":"v1","description":"Public REST API for Origonex: commodity supply-chain traceability and verification. See https://origonex.com/docs for the human-facing reference.","contact":{"name":"Origonex Support","url":"https://origonex.com/support"}},"servers":[{"url":"https://api.origonex.com/v1","description":"Production"},{"url":"https://api-staging.origonex.com/v1","description":"Staging"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key (`orx_…`, created in Settings → API keys with the scopes it needs) or a session token. The scope an operation needs is in its security requirement and in `x-origonex-scope`."}},"schemas":{"Tenant":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"slug":{"type":"string","pattern":"^[a-z][a-z0-9-]{0,63}$/u","description":"Tenant slug: URL-safe kebab-case"},"displayName":{"type":"string","minLength":1,"maxLength":200,"description":"Human-facing tenant name (shown in UI + DDS)"},"primaryCountry":{"type":["string","null"],"format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"plan":{"type":"string","enum":["starter","growth","scale","enterprise","importer","cooperative"],"description":"Subscription plan tier (read-only)"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","slug","displayName","primaryCountry","plan","createdAt","updatedAt"],"additionalProperties":false,"description":"Multi-tenant scope: the top-level isolation boundary"},"Problem":{"type":"object","properties":{"type":{"type":"string","description":"URI of the problem class."},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","description":"Stable machine-readable code; branch on this, not on `title` or `detail`."},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]},"description":"Per-field failures of a validation error."}},"required":["type","title","status","code"],"additionalProperties":{},"description":"RFC 9457 problem details"},"TenantPatch":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":200,"description":"Human-facing tenant name (shown in UI + DDS)"},"primaryCountry":{"type":["string","null"],"format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"}},"additionalProperties":false,"description":"Mutable subset of Tenant, for PATCH /v1/tenant"},"PartyList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Party"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"Party":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"otherKind":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"The company's name for the kind; required when kind is other"},"name":{"type":"string","minLength":1,"maxLength":300,"description":"Legal entity name"},"tradingName":{"type":["string","null"],"minLength":1,"maxLength":300},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"legalRegistrationNumber":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"Country-specific legal id (CNPJ / VAT / EIN / etc.)"},"eori":{"type":["string","null"],"pattern":"^[A-Z]{2}[A-Za-z0-9]{1,15}$/u"},"contactEmail":{"type":["string","null"],"maxLength":320,"format":"email"},"contactPhone":{"type":["string","null"],"pattern":"^\\+[1-9][0-9]{6,14}$/u"},"kycStatus":{"type":"string","enum":["not_started","pending","approved","rejected","expired"],"description":"KYC / KYB status: per-tenant onboarding flow"},"sanctionsMatch":{"type":"string","enum":["clear","weak","probable","confirmed","unscreenable"],"description":"Sanctions screening outcome, produced by the screening package (OFAC / EU / UK / UN / etc.). `unscreenable` is not a severity band: it means no comparison was possible, because the matcher scores Latin transliterations and the party's name is in a script it cannot read. Treat it as non-clear and requiring human review, never as an outcome."},"metadata":{"type":["object","null"],"additionalProperties":{}},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","tenantId","kind","otherKind","name","tradingName","country","legalRegistrationNumber","eori","contactEmail","contactPhone","kycStatus","sanctionsMatch","metadata","active","createdAt","updatedAt"],"additionalProperties":false},"PartyCreate":{"type":"object","properties":{"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"otherKind":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"The company's name for the kind; required when kind is other"},"name":{"type":"string","minLength":1,"maxLength":300,"description":"Legal entity name"},"tradingName":{"type":["string","null"],"minLength":1,"maxLength":300},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"legalRegistrationNumber":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"Country-specific legal id (CNPJ / VAT / EIN / etc.)"},"eori":{"type":["string","null"],"pattern":"^[A-Z]{2}[A-Za-z0-9]{1,15}$/u"},"contactEmail":{"type":["string","null"],"maxLength":320,"format":"email"},"contactPhone":{"type":["string","null"],"pattern":"^\\+[1-9][0-9]{6,14}$/u"},"metadata":{"type":["object","null"],"additionalProperties":{}},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["kind","name","tradingName","country","legalRegistrationNumber","eori","contactEmail","contactPhone","metadata"],"additionalProperties":false},"PartyPatch":{"type":"object","properties":{"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"otherKind":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"The company's name for the kind; required when kind is other"},"name":{"type":"string","minLength":1,"maxLength":300,"description":"Legal entity name"},"tradingName":{"type":["string","null"],"minLength":1,"maxLength":300},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"legalRegistrationNumber":{"type":["string","null"],"minLength":1,"maxLength":80,"description":"Country-specific legal id (CNPJ / VAT / EIN / etc.)"},"eori":{"type":["string","null"],"pattern":"^[A-Z]{2}[A-Za-z0-9]{1,15}$/u"},"contactEmail":{"type":["string","null"],"maxLength":320,"format":"email"},"contactPhone":{"type":["string","null"],"pattern":"^\\+[1-9][0-9]{6,14}$/u"},"metadata":{"type":["object","null"],"additionalProperties":{}}},"additionalProperties":false,"description":"PATCH /v1/parties/{id} payload"},"PlotList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Plot"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"Plot":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string","minLength":1,"maxLength":200},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"externalRef":{"type":["string","null"],"minLength":1,"maxLength":200},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"subdivision":{"type":["string","null"],"minLength":1,"maxLength":120},"geometryKind":{"type":"string","enum":["polygon","point"],"description":"How the plot is geolocated: a polygon, or a single point with a declared area (EUDR Art. 9(1)(d); Art. 2(28) for cattle)"},"polygon":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","items":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":4,"maxItems":50000},"minItems":1,"maxItems":500}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Polygon (RFC 7946 §3.1.6): coordinates as [lon, lat] tuples; first ring is outer boundary; subsequent rings are holes","format":"geojson"},"point":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"areaHectares":{"type":["number","null"],"minimum":0,"description":"Area in hectares: measured (polygon) or declared (point)"},"areaBasis":{"type":"string","enum":["measured","declared","unknown"],"description":"How areaHectares was obtained: measured from the polygon, declared by the operator for a point, or unclassified"},"declaredAreaHectares":{"type":["number","null"],"exclusiveMinimum":0},"centroid":{"type":"object","properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point centroid (server-computed)"},"registrySource":{"type":"string","enum":["car_sicar","sinaflor","sisbov","manual_upload","shapefile_import","satellite_traced","other"],"description":"Provenance of the plot polygon: CAR/SICAR (BR), Sinaflor (BR forestry), SISBOV (BR cattle), manual upload, shapefile import, or satellite-traced reconstruction"},"registryRef":{"type":["string","null"],"minLength":1,"maxLength":200},"deforestationRiskScore":{"type":["number","null"],"minimum":0,"maximum":100,"description":"Latest deforestation risk score (0=clean, 100=high risk) from the 1.5 risk-scoring engine"},"lastSatelliteScanAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","tenantId","name","ownerPartyId","externalRef","country","subdivision","geometryKind","polygon","point","areaHectares","areaBasis","declaredAreaHectares","centroid","registrySource","registryRef","deforestationRiskScore","lastSatelliteScanAt","active","createdAt","updatedAt"],"additionalProperties":false},"PointPlotRefused":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"reason":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","reason","detail"]},"PlotCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"externalRef":{"type":["string","null"],"minLength":1,"maxLength":200},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"subdivision":{"type":["string","null"],"minLength":1,"maxLength":120},"polygon":{"type":"object","properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","items":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":4,"maxItems":50000},"minItems":1,"maxItems":500}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Polygon (RFC 7946 §3.1.6): coordinates as [lon, lat] tuples; first ring is outer boundary; subsequent rings are holes","format":"geojson"},"point":{"type":"object","properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"declaredAreaHectares":{"type":"number","exclusiveMinimum":0,"maximum":99999999,"description":"Declared area in hectares, required with `point` (EUDR Art. 9(1)(d)); at most 4 ha unless every commodity is cattle (Art. 2(28))"},"commodities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":20},"registrySource":{"type":"string","enum":["car_sicar","sinaflor","sisbov","manual_upload","shapefile_import","satellite_traced","other"],"description":"Provenance of the plot polygon: CAR/SICAR (BR), Sinaflor (BR forestry), SISBOV (BR cattle), manual upload, shapefile import, or satellite-traced reconstruction"},"registryRef":{"type":["string","null"],"minLength":1,"maxLength":200},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["name","ownerPartyId","externalRef","country","subdivision","registrySource","registryRef"],"additionalProperties":false},"PlotPatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"externalRef":{"type":["string","null"],"minLength":1,"maxLength":200},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"subdivision":{"type":["string","null"],"minLength":1,"maxLength":120},"polygon":{"type":"object","properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","items":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":4,"maxItems":50000},"minItems":1,"maxItems":500}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Polygon (RFC 7946 §3.1.6): coordinates as [lon, lat] tuples; first ring is outer boundary; subsequent rings are holes","format":"geojson"},"point":{"type":"object","properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"declaredAreaHectares":{"type":"number","exclusiveMinimum":0,"maximum":99999999,"description":"Declared area in hectares, required with `point` (EUDR Art. 9(1)(d)); at most 4 ha unless every commodity is cattle (Art. 2(28))"},"commodities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":20},"registrySource":{"type":"string","enum":["car_sicar","sinaflor","sisbov","manual_upload","shapefile_import","satellite_traced","other"],"description":"Provenance of the plot polygon: CAR/SICAR (BR), Sinaflor (BR forestry), SISBOV (BR cattle), manual upload, shapefile import, or satellite-traced reconstruction"},"registryRef":{"type":["string","null"],"minLength":1,"maxLength":200}},"additionalProperties":false,"description":"PATCH /v1/plots/{id} payload: submitting a new polygon triggers a re-versioning row (audit trail preserved); on a point plot it converts the plot to a polygon. `point` / `declaredAreaHectares` restate a point plot and are refused on a polygon plot."},"TokenProof":{"type":"object","properties":{"chain":{"type":"string"},"contractAddress":{"type":"string"},"tokenId":{"type":["string","null"]},"anchorRoot":{"type":["string","null"]},"txHash":{"type":["string","null"]},"blockNumber":{"type":["string","null"]},"status":{"type":"string"},"confirmedAt":{"type":["string","null"]},"revoked":{"type":["object","null"],"properties":{"at":{"type":["string","null"]},"reason":{"type":["string","null"]}},"required":["at","reason"]}},"required":["chain","contractAddress","tokenId","anchorRoot","txHash","blockNumber","status","confirmedAt","revoked"]},"Label":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string","minLength":1,"maxLength":20},"commodity":{"type":"string","enum":["cattle","cocoa","coffee","palm_oil","rubber","soy","wood","derivative","sugarcane","fresh_produce","seafood","dairy","eggs","nut_butters"],"description":"Commodity carried by a batch/plot/shipment: the EUDR seven + derivative, plus the non-EUDR commodities served by shipping compliance profiles (Bonsucro sugarcane, US FSMA-204 food buckets)"},"quantity":{"type":"string"},"unit":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"producedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"producedByPartyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"producedByPartyName":{"type":["string","null"]},"tenantSlug":{"type":["string","null"],"pattern":"^[a-z][a-z0-9-]{0,63}$/u","description":"Tenant slug: URL-safe kebab-case"},"tenantName":{"type":["string","null"]},"anchor":{"type":["object","null"],"properties":{"publicToken":{"type":"string","format":"public-token","pattern":"^[A-Za-z0-9_-]{1,64}$/u","description":"256-bit CSPRNG capability token (base64url, ~43 chars)"},"status":{"type":"string","enum":["pending","submitted","confirmed","failed"],"description":"Anchoring lifecycle: pending (not yet submitted), submitted (tx in mempool / awaiting depth), confirmed (depth threshold reached), failed (reverted or replaced)"},"chain":{"type":"string","enum":["polygon_pos","polygon_amoy","ethereum_mainnet","hyperledger_fabric","noop"],"description":"Anchoring chain: polygon_pos is production default; polygon_amoy is testnet; ethereum_mainnet is Enterprise; hyperledger_fabric for permissioned consortia; noop for tests"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["publicToken","status","chain","revokedAt"],"additionalProperties":false},"payload":{"type":["object","null"],"properties":{"url":{"type":"string","maxLength":2000,"format":"uri","description":"RFC 3986 URI"},"mode":{"type":"string","enum":["verifier","gs1_digital_link"]}},"required":["url","mode"],"additionalProperties":false},"verifierBase":{"type":"string","maxLength":2000,"format":"uri","description":"RFC 3986 URI"}},"required":["batchId","lotCode","commodity","quantity","unit","producedAt","producedByPartyId","producedByPartyName","tenantSlug","tenantName","anchor","payload","verifierBase"],"additionalProperties":false,"description":"Everything needed to place a mark for a batch on packaging: the payload URL it encodes plus the facts printed beside it"},"CustodyStatus":{"type":"object","properties":{"enabled":{"type":"boolean","enum":[true]}},"required":["enabled"]},"CustodyStageTemplateList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"commodity":{"type":"string","enum":["wood","cattle","coffee","cocoa","palm_oil","soy","rubber"]},"version":{"type":"string","description":"Semantic version; a record stores the version it was checked against, so a later change never re-judges history."},"criticalLink":{"type":"object","properties":{"stage":{"type":"string"},"check":{"type":"string"}},"required":["stage","check"],"additionalProperties":false,"description":"Where this chain is most exposed, and the check that watches it."},"stages":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable stage key, e.g. `logs`, `ffb`, `carcass`."},"labelKey":{"type":"string","description":"Translation key of the stage name (`custody.stages.<key>`)."},"allowedUnits":{"type":"array","items":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"description":"Units a lot at this stage is recorded in (a lot’s `unitType`)."},"expectedDocuments":{"type":"array","items":{"type":"string"},"description":"Document types typically carried at this stage (e.g. `dof`, `gta`, `romaneio`)."},"expectedDocumentChoices":{"type":"array","items":{"type":"object","properties":{"anyOf":{"type":"array","items":{"type":"string"}}},"required":["anyOf"],"additionalProperties":false},"description":"Documents expected as one of a set, because which one depends on the origin: e.g. `autex` or `autef` for the harvest, `dof` or `gf` for transport (Pará and Mato Grosso issue their own)."},"expectedDocumentsWhen":{"type":"object","additionalProperties":{"type":"string","enum":["export","moved"]},"description":"Expected documents that apply only in a context: `export` once the lot is in a shipment that crosses a border (e.g. the commercial invoice), `moved` once it was carried or shipped (e.g. an NF-e). A document not named here is expected in any context."},"siteKinds":{"type":"array","items":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"]},"description":"Kinds of site where this stage typically happens."},"shrink":{"type":"object","properties":{"maxLossPct":{"type":"number","minimum":0,"maximum":100},"maxGainPct":{"type":"number","minimum":0,"maximum":100},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["maxLossPct","maxGainPct","source"],"additionalProperties":false,"description":"Tolerance on a receipt of material at this stage: how much less (loss) or more (gain) than was dispatched may arrive before it is flagged. Gaining is the suspect direction."},"grading":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"measure":{"type":"string","enum":["percent"]},"partialAbove":{"type":"number","minimum":0,"maximum":100},"partialBelow":{"type":"number","minimum":0,"maximum":100},"deduction":{"type":"string","enum":["dry_matter","content_ratio","excess_share"],"description":"How a breach is settled on a receipt: dry_matter (moisture: the dry-matter weight at the limit), content_ratio (a content floor: the weight holding the expected content), excess_share (the share over the limit is refused)."},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["key","measure","deduction","source"],"additionalProperties":false},"description":"Measurements a receiver may record for material at this stage; past its one threshold, the line is settled by its `deduction` and a full acceptance becomes partial."},"maxHoldHours":{"type":"integer","exclusiveMinimum":0,"description":"Material at this stage should move on within this many hours."}},"required":["key","labelKey","allowedUnits","expectedDocuments","siteKinds","shrink"],"additionalProperties":false},"description":"In chain order."},"transitions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"from":{"type":"array","items":{"type":"string"},"description":"Stages the inputs may be at."},"to":{"type":"array","items":{"type":"string"},"description":"Stages the step produces; the first is the primary output."},"kind":{"type":"string","enum":["process","split","merge","pack","slaughter"]},"yield":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"typical":{"type":"number"},"measure":{"type":"string","enum":["mass","volume"]},"basis":{"type":["string","null"],"description":"Calculator the range was taken from, or null for a reference value."},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["min","max","typical","measure","basis","source"],"additionalProperties":false,"description":"Expected primary output ÷ input. A yield outside the range is recorded and flagged, never refused."},"lossKinds":{"type":"array","items":{"type":"string","enum":["sawdust","bark","trim","moisture","offal","blood","bone","mortality","pulp","husk","defects","chaff","shell","fiber","kernel","empty_bunch","sludge","fatty_acids","hull","foreign_matter"]}},"multiOutput":{"type":"array","items":{"type":"object","properties":{"stage":{"type":"string"},"share":{"type":"number"}},"required":["stage","share"],"additionalProperties":false},"description":"Typical share of the input that becomes each output."},"byProducts":{"type":"array","items":{"type":"string"},"description":"Stages the step may also produce as lots of their own, when the company keeps them (a sawmill’s offcuts and sawdust). Never part of the yield, which is the first `to` stage’s."}},"required":["key","from","to","kind","lossKinds"],"additionalProperties":false}}},"required":["commodity","version","criticalLink","stages","transitions"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"CustodyProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyStageTemplate":{"type":"object","properties":{"commodity":{"type":"string","enum":["wood","cattle","coffee","cocoa","palm_oil","soy","rubber"]},"version":{"type":"string","description":"Semantic version; a record stores the version it was checked against, so a later change never re-judges history."},"criticalLink":{"type":"object","properties":{"stage":{"type":"string"},"check":{"type":"string"}},"required":["stage","check"],"additionalProperties":false,"description":"Where this chain is most exposed, and the check that watches it."},"stages":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable stage key, e.g. `logs`, `ffb`, `carcass`."},"labelKey":{"type":"string","description":"Translation key of the stage name (`custody.stages.<key>`)."},"allowedUnits":{"type":"array","items":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"description":"Units a lot at this stage is recorded in (a lot’s `unitType`)."},"expectedDocuments":{"type":"array","items":{"type":"string"},"description":"Document types typically carried at this stage (e.g. `dof`, `gta`, `romaneio`)."},"expectedDocumentChoices":{"type":"array","items":{"type":"object","properties":{"anyOf":{"type":"array","items":{"type":"string"}}},"required":["anyOf"],"additionalProperties":false},"description":"Documents expected as one of a set, because which one depends on the origin: e.g. `autex` or `autef` for the harvest, `dof` or `gf` for transport (Pará and Mato Grosso issue their own)."},"expectedDocumentsWhen":{"type":"object","additionalProperties":{"type":"string","enum":["export","moved"]},"description":"Expected documents that apply only in a context: `export` once the lot is in a shipment that crosses a border (e.g. the commercial invoice), `moved` once it was carried or shipped (e.g. an NF-e). A document not named here is expected in any context."},"siteKinds":{"type":"array","items":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"]},"description":"Kinds of site where this stage typically happens."},"shrink":{"type":"object","properties":{"maxLossPct":{"type":"number","minimum":0,"maximum":100},"maxGainPct":{"type":"number","minimum":0,"maximum":100},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["maxLossPct","maxGainPct","source"],"additionalProperties":false,"description":"Tolerance on a receipt of material at this stage: how much less (loss) or more (gain) than was dispatched may arrive before it is flagged. Gaining is the suspect direction."},"grading":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"measure":{"type":"string","enum":["percent"]},"partialAbove":{"type":"number","minimum":0,"maximum":100},"partialBelow":{"type":"number","minimum":0,"maximum":100},"deduction":{"type":"string","enum":["dry_matter","content_ratio","excess_share"],"description":"How a breach is settled on a receipt: dry_matter (moisture: the dry-matter weight at the limit), content_ratio (a content floor: the weight holding the expected content), excess_share (the share over the limit is refused)."},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["key","measure","deduction","source"],"additionalProperties":false},"description":"Measurements a receiver may record for material at this stage; past its one threshold, the line is settled by its `deduction` and a full acceptance becomes partial."},"maxHoldHours":{"type":"integer","exclusiveMinimum":0,"description":"Material at this stage should move on within this many hours."}},"required":["key","labelKey","allowedUnits","expectedDocuments","siteKinds","shrink"],"additionalProperties":false},"description":"In chain order."},"transitions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"from":{"type":"array","items":{"type":"string"},"description":"Stages the inputs may be at."},"to":{"type":"array","items":{"type":"string"},"description":"Stages the step produces; the first is the primary output."},"kind":{"type":"string","enum":["process","split","merge","pack","slaughter"]},"yield":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"typical":{"type":"number"},"measure":{"type":"string","enum":["mass","volume"]},"basis":{"type":["string","null"],"description":"Calculator the range was taken from, or null for a reference value."},"source":{"type":"string","description":"Where the value comes from: the published source of its reference values, or `origonex_default` for an Origonex reference default. These are reference defaults that guide and flag, not regulatory tolerances."}},"required":["min","max","typical","measure","basis","source"],"additionalProperties":false,"description":"Expected primary output ÷ input. A yield outside the range is recorded and flagged, never refused."},"lossKinds":{"type":"array","items":{"type":"string","enum":["sawdust","bark","trim","moisture","offal","blood","bone","mortality","pulp","husk","defects","chaff","shell","fiber","kernel","empty_bunch","sludge","fatty_acids","hull","foreign_matter"]}},"multiOutput":{"type":"array","items":{"type":"object","properties":{"stage":{"type":"string"},"share":{"type":"number"}},"required":["stage","share"],"additionalProperties":false},"description":"Typical share of the input that becomes each output."},"byProducts":{"type":"array","items":{"type":"string"},"description":"Stages the step may also produce as lots of their own, when the company keeps them (a sawmill’s offcuts and sawdust). Never part of the yield, which is the first `to` stage’s."}},"required":["key","from","to","kind","lossKinds"],"additionalProperties":false}}},"required":["commodity","version","criticalLink","stages","transitions"],"additionalProperties":false},"TagResolution":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["resolved"]},"via":{"type":"string","enum":["tag","verifier_link","digital_link"]},"tagId":{"type":["string","null"]},"batch":{"type":"object","properties":{"id":{"type":"string"},"lotCode":{"type":"string"},"commodity":{"type":"string"}},"required":["id","lotCode","commodity"],"additionalProperties":false},"unit":{"type":"object","properties":{"id":{"type":"string"},"serial":{"type":"string"},"gtin":{"type":["string","null"]},"status":{"type":"string","enum":["active","voided"]}},"required":["id","serial","gtin","status"],"additionalProperties":false}},"required":["status","via","tagId","batch"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","enum":["revoked"]},"tagId":{"type":"string"},"revokedAt":{"type":"string"},"batch":{"type":["object","null"],"properties":{"id":{"type":"string"},"lotCode":{"type":"string"},"commodity":{"type":"string"}},"required":["id","lotCode","commodity"],"additionalProperties":false}},"required":["status","tagId","revokedAt","batch"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","enum":["unbound"]},"tagId":{"type":"string"}},"required":["status","tagId"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","enum":["vehicle"]},"vehicle":{"type":"object","properties":{"id":{"type":"string"},"plate":{"type":"string"},"kind":{"type":"string"}},"required":["id","plate","kind"],"additionalProperties":false}},"required":["status","vehicle"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","enum":["unknown"]}},"required":["status"],"additionalProperties":false}]},"TagResolveRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["qr","datamatrix","barcode","nfc_ntag","nfc_ntag_424_dna","rfid_uhf","rfid_hf","tamper_seal","dna_marker"]},"value":{"type":"string","minLength":1,"maxLength":2048}},"required":["kind","value"],"additionalProperties":false},"BoundTag":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["qr","datamatrix","barcode","nfc_ntag","nfc_ntag_424_dna","rfid_uhf","rfid_hf","tamper_seal","dna_marker"]},"value":{"type":"string"},"batchId":{"type":["string","null"]},"issuedAt":{"type":"string"},"revokedAt":{"type":["string","null"]}},"required":["id","kind","value","batchId","issuedAt","revokedAt"],"additionalProperties":false},"TagBindRequest":{"type":"object","properties":{"batchId":{"type":"string","minLength":1,"maxLength":64},"move":{"type":"boolean"}},"required":["batchId"],"additionalProperties":false},"TagLinkRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["qr","datamatrix","barcode","nfc_ntag","nfc_ntag_424_dna","rfid_uhf","rfid_hf","tamper_seal","dna_marker"]},"value":{"type":"string","minLength":1,"maxLength":2048},"meta":{"type":"object","additionalProperties":{}},"batchId":{"type":"string","minLength":1,"maxLength":64},"move":{"type":"boolean"}},"required":["kind","value","batchId"],"additionalProperties":false},"CustodyEvent":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"kind":{"type":"string","enum":["record","correction","retraction"]},"occurredAt":{"type":"string"},"recordedAt":{"type":"string"},"recordedBy":{"type":["string","null"]},"operator":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["user"]},"name":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["member"]}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"],"additionalProperties":false},{"type":"null"}]},"apiKey":{"type":["object","null"],"properties":{"name":{"type":"string"},"revoked":{"type":"boolean"}},"required":["name","revoked"],"additionalProperties":false},"location":{"type":["object","null"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}},"required":["lat","lng"],"additionalProperties":false},"source":{"type":"string"},"payload":{"type":"object","additionalProperties":{}},"untypedCapture":{"type":"object","properties":{"note":{"type":"string"},"weight":{"type":"string"}},"additionalProperties":false},"payloadVersion":{"type":"integer"},"clockSuspect":{"type":"boolean"},"supersedesEventId":{"type":["string","null"]},"reason":{"type":["string","null"]},"correctedById":{"type":["string","null"]},"correctionRetracted":{"type":"boolean"},"deviceSignature":{"type":["string","null"],"enum":["verified","bad_signature","photos_mismatch","unknown_key","revoked_key",null],"description":"`verified`: signed on the device: the phone’s registered key signed this event and these files. Every other value flags the event, which is kept: `bad_signature` (the event recorded is not what the phone signed, or another key signed it), `photos_mismatch` (the files are not the ones signed), `unknown_key` (no key of this user in this workspace has that id), `revoked_key` (the key was revoked before the event arrived)."},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","eventType","kind","occurredAt","recordedAt","recordedBy","operator","apiKey","location","source","payload","untypedCapture","payloadVersion","clockSuspect","supersedesEventId","reason","correctedById","correctionRetracted","deviceSignature"],"additionalProperties":false},"CustodyEventCorrection":{"type":"object","properties":{"occurredAt":{"type":"string","format":"date-time"},"deviceSentAt":{"type":"string","format":"date-time"},"payload":{"type":"object","additionalProperties":{}},"reason":{"type":"string","minLength":3,"maxLength":500},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["reason"],"additionalProperties":false},"CustodyEventRetraction":{"type":"object","properties":{"reason":{"type":"string","minLength":3,"maxLength":500}},"required":["reason"],"additionalProperties":false},"CustodyEventHistory":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/CustodyEvent"},"description":"The shape this list answered before (absent with `shape=v2`)."},"nextCursor":{"type":["string","null"],"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyEvent"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"PageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"],"description":"Where the next page starts; `nextCursor` is null on the last page."},"SiteList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Site"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"Site":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"],"description":"What kind of place the site is"},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Name people use for it"},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Owner party; null when the site is the tenant's own"},"responsibleUserId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The workspace member responsible for the site"},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"addressLine":{"type":["string","null"],"minLength":1,"maxLength":200},"city":{"type":["string","null"],"minLength":1,"maxLength":200},"region":{"type":["string","null"],"minLength":1,"maxLength":200},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":32},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"kindOther":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"deletedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","tenantId","kind","name","ownerPartyId","responsibleUserId","location","addressLine","city","region","postalCode","country","kindOther","createdAt","updatedAt","deletedAt"],"additionalProperties":false},"SiteProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"SiteCreate":{"type":"object","properties":{"kind":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"],"description":"What kind of place the site is"},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Name people use for it"},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Owner party; null when the site is the tenant's own"},"responsibleUserId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The workspace member responsible for the site"},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"addressLine":{"type":["string","null"],"minLength":1,"maxLength":200},"city":{"type":["string","null"],"minLength":1,"maxLength":200},"region":{"type":["string","null"],"minLength":1,"maxLength":200},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":32},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"kindOther":{"type":["string","null"],"minLength":1,"maxLength":120,"description":"What an `other` place is (only with kind `other`)"},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["kind","name","country"],"additionalProperties":false},"SitePatch":{"type":"object","properties":{"kind":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"],"description":"What kind of place the site is"},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Name people use for it"},"ownerPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Owner party; null when the site is the tenant's own"},"responsibleUserId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The workspace member responsible for the site"},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"addressLine":{"type":["string","null"],"minLength":1,"maxLength":200},"city":{"type":["string","null"],"minLength":1,"maxLength":200},"region":{"type":["string","null"],"minLength":1,"maxLength":200},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":32},"country":{"type":"string","format":"country-iso-3166-1-alpha-2","pattern":"^[A-Z]{2}$/u","description":"ISO 3166-1 alpha-2 country code"},"kindOther":{"type":["string","null"],"minLength":1,"maxLength":120,"description":"What an `other` place is (only with kind `other`)"}},"additionalProperties":false,"description":"PATCH /v1/custody/sites/{id} payload"},"CustodyLotPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyLot"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"]},"CustodyLot":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string","description":"The code on the label and the paperwork"},"commodity":{"type":"string"},"quantity":{"type":"string","pattern":"^\\d{1,15}(\\.\\d{1,3})?$/u","description":"Decimal text, up to three decimals, in `unitType`"},"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"producedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"producedByPartyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"chainType":{"type":"string","enum":["identity_preserved","segregated","mass_balance","book_and_claim"],"description":"Chain-of-custody model: IP keeps physical separation from origin to point of sale; segregated mixes equivalent certified material; mass balance allows controlled blending with reconciliation; book-and-claim decouples physical and certificate flow (RSPO / RTRS / Bonsucro hybrid models)"},"parentBatchIds":{"type":"array","items":{"type":"string"}},"childBatchIds":{"type":"array","items":{"type":"string"}},"sourcePlotIds":{"type":"array","items":{"type":"string"}},"contributingPartyIds":{"type":"array","items":{"type":"string"}},"hsCode":{"type":["string","null"]},"originCountry":{"type":["string","null"]},"stage":{"type":["string","null"],"description":"The stage of its commodity’s chain the lot was recorded at, if any"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"deletedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","lotCode","commodity","quantity","unitType","producedAt","producedByPartyId","chainType","parentBatchIds","childBatchIds","sourcePlotIds","contributingPartyIds","hsCode","originCountry","stage","createdAt","updatedAt","deletedAt"],"additionalProperties":false},"CursorProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyRecordProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyLotCreate":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{15,63}$/u"},"commodity":{"type":"string","minLength":1,"maxLength":64},"lotCode":{"type":"string","minLength":1,"maxLength":20},"weightKg":{"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":1000000000},{"type":"string","pattern":"^\\d{1,15}(\\.\\d{1,3})?$/u"}]},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"producedAt":{"type":"string","format":"date-time"},"producedByParty":{"type":"string","minLength":1,"maxLength":64},"chainType":{"type":"string","enum":["segregated","mass_balance"]},"parentBatchIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":50},"childBatchIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":50},"sourcePlotIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":200},"contributingPartyIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":500},"hsCode":{"type":["string","null"],"pattern":"^\\d{4,10}$/u"},"originCountry":{"type":["string","null"],"pattern":"^[A-Z]{2}$/u"},"species":{"type":"array","items":{"type":"object","properties":{"scientificName":{"type":"string","minLength":1,"maxLength":200},"commonName":{"type":"string","minLength":1,"maxLength":200}},"required":["scientificName"],"additionalProperties":false},"maxItems":500},"captureLocation":{"type":["object","null"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"accuracyM":{"type":["number","null"],"minimum":0,"maximum":100000},"fromCache":{"type":"boolean"}},"required":["lat","lng"]},"stage":{"type":"string","minLength":1,"maxLength":40},"capturedAt":{"type":"string","format":"date-time"},"deviceSentAt":{"type":"string","format":"date-time"},"meta":{},"idempotencyKey":{"type":"string","minLength":1,"maxLength":64},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["commodity","weightKg","unitType","producedAt","producedByParty"]},"CustodyCertificateRecordPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyCertificateRecord"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"]},"CustodyCertificateRecord":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"certifier":{"type":"string"},"certifierCustom":{"type":["string","null"]},"certificateNumber":{"type":"string"},"subjectType":{"type":"string"},"subjectId":{"type":"string"},"validFrom":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"validUntil":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"documentId":{"type":["string","null"]},"verifiedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"registryStatus":{"type":["string","null"],"description":"The certifier’s registry’s answer at the last check, if any"},"registryCheckedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"deletedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","certifier","certifierCustom","certificateNumber","subjectType","subjectId","validFrom","validUntil","documentId","verifiedAt","registryStatus","registryCheckedAt","createdAt","updatedAt","deletedAt"],"additionalProperties":false,"description":"A certificate held by a party, a plot, a site or a lot"},"CustodyCertificateCreate":{"type":"object","properties":{"certifier":{"type":"string","enum":["fsc","rainforest_alliance","bonsucro","rspo","rtrs","proterra","iscc","fairtrade","globalgap","organic_usda","organic_eu","organic_ibd_br","halal","kosher","pefc","cerflor","four_c","custom"]},"certifierCustom":{"type":["string","null"],"maxLength":120},"certificateNumber":{"type":"string","minLength":1,"maxLength":120},"subjectType":{"type":"string","enum":["plot","batch","shipment","party","site","transformation","certificate","document","dds"]},"subjectId":{"type":"string","minLength":1,"maxLength":64},"validFrom":{"type":"string"},"validUntil":{"type":"string"},"scope":{},"documentId":{"type":["string","null"],"minLength":1,"maxLength":64},"verifiedAt":{"type":["string","null"],"format":"date-time"},"meta":{},"renews":{"type":"string","minLength":1,"maxLength":64}},"required":["certifier","certificateNumber","subjectType","subjectId","validFrom","validUntil"]},"CustodyClaimDeclarationPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyClaimDeclaration"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"]},"CustodyClaimDeclaration":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"category":{"type":"string","enum":["fsc_100","fsc_mix_percent","fsc_mix_credit","fsc_controlled_wood","pefc_certified","pefc_controlled_sources","rspo_identity_preserved","rspo_segregated","rspo_mass_balance","ra_identity_preserved","ra_mixed_identity_preserved","ra_segregated","ra_mass_balance","fairtrade_segregated","fairtrade_mass_balance","rtrs_segregated","rtrs_mass_balance","proterra_identity_preserved","proterra_segregated","four_c_segregated","four_c_mass_balance"]},"percentage":{"type":["integer","null"]},"originRef":{"type":["string","null"]},"certificateCode":{"type":["string","null"]},"certificateId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"supersedesId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"note":{"type":["string","null"]},"declaredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"source":{"type":"string"},"contentSha256":{"type":"string"}},"required":["id","batchId","scheme","category","percentage","originRef","certificateCode","certificateId","supersedesId","note","declaredAt","source","contentSha256"],"additionalProperties":false},"VehicleList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Vehicle"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"Vehicle":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plate":{"type":"string"},"kind":{"type":"string","enum":["truck","trailer","boat","wagon","other"],"description":"What the vehicle is: truck, trailer, boat, rail wagon, other"},"capacity":{"type":["number","null"],"exclusiveMinimum":0,"maximum":1000000000,"description":"How much the vehicle carries, in `capacityUnit`"},"capacityUnit":{"type":["string","null"],"enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch",null],"description":"Unit of a custody quantity. Mass units are always stated in kilograms (the name gives the product form, not the scale); volumes in the unit itself; counts as the count."},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Carrier party; null when the vehicle is the tenant's own"},"tagValue":{"type":["string","null"],"minLength":1,"maxLength":512,"description":"The value of a QR, barcode or NFC tag fixed to the vehicle, exactly as a scanner reads it. Scanning it resolves to this vehicle."},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"deletedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","tenantId","plate","kind","capacity","capacityUnit","carrierPartyId","tagValue","createdAt","updatedAt","deletedAt"],"additionalProperties":false,"description":"A vehicle that carries custody between places"},"VehicleProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"VehicleCreate":{"type":"object","properties":{"plate":{"type":"string","maxLength":40,"description":"Registration plate. Stored normalised: upper case, without spaces, hyphens or dots. Sensitive for visibility (never public by default)."},"kind":{"type":"string","enum":["truck","trailer","boat","wagon","other"],"description":"What the vehicle is: truck, trailer, boat, rail wagon, other"},"capacity":{"type":["number","null"],"exclusiveMinimum":0,"maximum":1000000000,"description":"How much the vehicle carries, in `capacityUnit`"},"capacityUnit":{"type":["string","null"],"enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch",null],"description":"Unit of a custody quantity. Mass units are always stated in kilograms (the name gives the product form, not the scale); volumes in the unit itself; counts as the count."},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tagValue":{"type":["string","null"],"minLength":1,"maxLength":512,"description":"The value of a QR, barcode or NFC tag fixed to the vehicle, exactly as a scanner reads it. Scanning it resolves to this vehicle."}},"required":["plate","kind"],"additionalProperties":false,"description":"POST /v1/custody/vehicles payload"},"VehiclePatch":{"type":"object","properties":{"plate":{"type":"string","maxLength":40,"description":"Registration plate. Stored normalised: upper case, without spaces, hyphens or dots. Sensitive for visibility (never public by default)."},"kind":{"type":"string","enum":["truck","trailer","boat","wagon","other"],"description":"What the vehicle is: truck, trailer, boat, rail wagon, other"},"capacity":{"type":["number","null"],"exclusiveMinimum":0,"maximum":1000000000,"description":"How much the vehicle carries, in `capacityUnit`"},"capacityUnit":{"type":["string","null"],"enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch",null],"description":"Unit of a custody quantity. Mass units are always stated in kilograms (the name gives the product form, not the scale); volumes in the unit itself; counts as the count."},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tagValue":{"type":["string","null"],"minLength":1,"maxLength":512,"description":"The value of a QR, barcode or NFC tag fixed to the vehicle, exactly as a scanner reads it. Scanning it resolves to this vehicle."}},"additionalProperties":false,"description":"PATCH /v1/custody/vehicles/{id} payload"},"DriverList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Driver"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"Driver":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Carrier party; null when the driver drives for the tenant's own fleet"},"personalDataRef":{"type":"string","description":"Pseudonymous reference into the personal-data vault. Custody records and the audit trail carry this, never the name."},"identityState":{"type":"string","enum":["live","erased","unreadable"],"description":"`live`: the identity is held; `erased`: the person was erased (the reference stays); `unreadable`: held but could not be opened by this server"},"identity":{"type":["object","null"],"properties":{"fullName":{"type":"string","minLength":1,"maxLength":200,"description":"Full name"},"documentType":{"type":"string","enum":["cpf","cnh","rg","passport","national_id","other"],"description":"Kind of identity document"},"documentNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Identity document number (e.g. a CPF)"},"licenceNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Driving licence number"}},"required":["fullName"],"additionalProperties":false,"description":"A driver's identity, held in the erasable personal-data vault"},"licenceCategory":{"type":["string","null"]},"licenceExpiresOn":{"type":["string","null"],"format":"date"},"identityMasked":{"type":"boolean","description":"True when the document and licence numbers are masked to their last three characters (`···725`) because the caller is below `master_data:approve`"},"erasedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"deletedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","tenantId","carrierPartyId","personalDataRef","identityState","identity","licenceCategory","licenceExpiresOn","identityMasked","erasedAt","createdAt","updatedAt","deletedAt"],"additionalProperties":false,"description":"A driver; the identity lives in an erasable vault"},"DriverProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"DriverCreate":{"type":"object","properties":{"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"identity":{"type":"object","properties":{"fullName":{"type":"string","minLength":1,"maxLength":200,"description":"Full name"},"documentType":{"type":"string","enum":["cpf","cnh","rg","passport","national_id","other"],"description":"Kind of identity document"},"documentNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Identity document number (e.g. a CPF)"},"licenceNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Driving licence number"}},"required":["fullName"],"additionalProperties":false,"description":"A driver's identity, held in the erasable personal-data vault"},"licenceCategory":{"type":["string","null"],"description":"Driving licence category as registered (CNH `C`, `AE`…)"},"licenceExpiresOn":{"type":["string","null"],"format":"date","description":"The driving licence's last valid day, YYYY-MM-DD"}},"required":["identity"],"additionalProperties":false,"description":"POST /v1/custody/drivers payload"},"DriverPatch":{"type":"object","properties":{"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"licenceCategory":{"type":["string","null"],"description":"Driving licence category as registered (CNH `C`, `AE`…)"},"licenceExpiresOn":{"type":["string","null"],"format":"date","description":"The driving licence's last valid day, YYYY-MM-DD"}},"additionalProperties":false,"description":"PATCH /v1/custody/drivers/{id} payload"},"DriverIdentity":{"type":"object","properties":{"fullName":{"type":"string","minLength":1,"maxLength":200,"description":"Full name"},"documentType":{"type":"string","enum":["cpf","cnh","rg","passport","national_id","other"],"description":"Kind of identity document"},"documentNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Identity document number (e.g. a CPF)"},"licenceNumber":{"type":"string","minLength":1,"maxLength":64,"description":"Driving licence number"}},"required":["fullName"],"additionalProperties":false,"description":"A driver's identity, held in the erasable personal-data vault"},"CustodyTransformation":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["process","split","merge","pack","slaughter","legacy_link"]},"chainType":{"type":"string","enum":["segregated","mass_balance"],"description":"Segregated only when every input is; a mass-balance input makes the step mass balance. Omit it to have it derived."},"commodity":{"type":["string","null"]},"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"siteName":{"type":["string","null"]},"siteLocation":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"recordedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"source":{"type":"string","enum":["web","mobile","api","hardware_bridge","cron","registry_sync"]},"template":{"type":["object","null"],"properties":{"version":{"type":"string"},"transitionKey":{"type":["string","null"]},"yield":{"type":["object","null"],"properties":{"min":{"type":"number"},"max":{"type":"number"},"typical":{"type":"number"},"measure":{"type":"string"},"basis":{"type":["string","null"]},"source":{"type":"string"}},"required":["min","max","typical","measure","basis","source"],"additionalProperties":false},"yieldUpperBound":{"type":["number","null"]}},"required":["version","transitionKey","yield","yieldUpperBound"],"additionalProperties":false,"description":"The template version and range the step was judged against"},"measuredYield":{"type":["number","null"]},"conversionFactor":{"type":["object","null"],"properties":{"value":{"type":"number"},"source":{"type":"string","enum":["template","technical_study"]},"reference":{"type":["string","null"]}},"required":["value","source","reference"],"additionalProperties":false},"expectedOutput":{"type":["number","null"]},"unitFactors":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"to":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"ratio":{"type":"number"}},"required":["from","to","ratio"],"additionalProperties":false}},"balance":{"type":"object","properties":{"unit":{"type":["string","null"],"enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch",null],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"inputTotal":{"type":["number","null"]},"outputTotal":{"type":["number","null"]},"lossTotal":{"type":["number","null"]},"toleranceRatio":{"type":"number"}},"required":["unit","inputTotal","outputTotal","lossTotal","toleranceRatio"],"additionalProperties":false},"alerts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["yield_above_range","yield_below_range","yield_not_assessable","transition_not_in_template","unaccounted_quantity","losses_exceed_input","balance_not_assessable","input_at_other_site"]}},"required":["code"],"additionalProperties":{},"description":"A flag the step was recorded with, never a refusal. `yield_above_range` carries `measured` and `max`; `unaccounted_quantity` carries `gap` and `unit`; the others carry what they name."}},"quantitiesKnown":{"type":"boolean","description":"False only on a migrated `legacy_link`: a parent → child link that existed before quantities were recorded. It says which lots went in, not how much: each input line carries that lot’s own recorded quantity (the most it could have given, not what it gave), and the step is left out of every balance."},"note":{"type":["string","null"]},"reference":{"type":["string","null"]},"attachments":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"contentSha256":{"type":"string"},"childrenRoot":{"type":["string","null"]},"inputs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"quantity":{"type":"number"},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"stage":{"type":["string","null"]}},"required":["id","batchId","lotCode","quantity","unitType","stage"],"additionalProperties":false}},"outputs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"quantity":{"type":"number"},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"stage":{"type":["string","null"]},"claim":{"type":["object","null"],"properties":{"category":{"type":["string","null"],"enum":["fsc_100","fsc_mix_percent","fsc_mix_credit","fsc_controlled_wood","pefc_certified","pefc_controlled_sources","rspo_identity_preserved","rspo_segregated","rspo_mass_balance","ra_identity_preserved","ra_mixed_identity_preserved","ra_segregated","ra_mass_balance","fairtrade_segregated","fairtrade_mass_balance","rtrs_segregated","rtrs_mass_balance","proterra_identity_preserved","proterra_segregated","four_c_segregated","four_c_mass_balance",null],"description":"Null under a claimed step: an RSPO mass-balance output its account could not cover carries no claim."},"percentage":{"type":["integer","null"],"minimum":1,"maximum":100},"originRef":{"type":["string","null"],"description":"The single origin of an IP claim"},"creditDebit":{"type":["string","null"],"pattern":"^-?\\d+\\.\\d{3}$/u","description":"What it drew from its credit account"},"accountId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["category","percentage","originRef","creditDebit","accountId"],"additionalProperties":false,"description":"The claim the output lot carries (CUS-205); null: the step named no scheme"}},"required":["id","batchId","lotCode","quantity","unitType","stage","claim"],"additionalProperties":false}},"claim":{"type":["object","null"],"properties":{"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"system":{"type":"string","enum":["transfer","percentage","credit","identity_preserved","segregated","mass_balance","mixed_identity_preserved"],"description":"The control system: FSC and PEFC `transfer` (PEFC: physical separation), `percentage`, `credit`; RSPO `identity_preserved`, `segregated`, `mass_balance`; Rainforest Alliance `identity_preserved`, `segregated`, `mass_balance` (not for coffee: CUS-602), `mixed_identity_preserved`; Fairtrade and RTRS `segregated`, `mass_balance`; ProTerra `identity_preserved`, `segregated`."},"inputPercentage":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"The certified share of the inputs, whole percent, rounded down"},"credits":{"type":"array","items":{"type":"object","properties":{"accountId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"productClass":{"type":"string"},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"balanceBefore":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"creditsIn":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"creditsOut":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"balanceAfter":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"}},"required":["accountId","productClass","unitType","balanceBefore","creditsIn","creditsOut","balanceAfter"],"additionalProperties":false}},"alerts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["claim_below_label_threshold","claim_credit_short"]}},"required":["code"],"additionalProperties":{}},"description":"`claim_below_label_threshold` (a percentage below 70: on the invoice, not on a label); `claim_credit_short` (an output its account could not cover whole: Controlled Wood / Controlled Sources / no RSPO claim)."}},"required":["scheme","system","inputPercentage","credits","alerts"],"additionalProperties":false,"description":"The certification scheme and control system the step was run under, and what the claim computation recorded (CUS-205); null: none"},"losses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string"},"quantity":{"type":"number"},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."}},"required":["id","kind","quantity","unitType"],"additionalProperties":false}},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","kind","chainType","commodity","siteId","siteName","siteLocation","occurredAt","recordedAt","source","template","measuredYield","conversionFactor","expectedOutput","unitFactors","balance","alerts","quantitiesKnown","note","reference","attachments","contentSha256","childrenRoot","inputs","outputs","claim","losses"],"additionalProperties":false},"CustodyTransformationProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyTransformationRecord":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["process","split","merge","pack","slaughter"],"description":"What the step does: split one lot into several, merge several into one, process (sawing, crushing, hulling…), pack, or slaughter."},"chainType":{"type":"string","enum":["segregated","mass_balance"],"description":"Segregated only when every input is; a mass-balance input makes the step mass balance. Omit it to have it derived."},"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The site where it happened"},"occurredAt":{"type":"string","format":"date-time","description":"When it happened on the ground"},"inputs":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"How much of the lot the step consumes, in the lot’s own unit"}},"required":["batchId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":100},"outputs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"Quantity in the unit, at most three decimals (a count is whole)."},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"commodity":{"type":"string","minLength":1,"maxLength":64,"description":"Defaults to the inputs’ commodity"},"stage":{"type":["string","null"],"maxLength":40,"pattern":"^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/u","description":"A stage key of the commodity’s template (`logs`, `sawn_timber`…)."},"lotCode":{"type":["string","null"],"minLength":1,"maxLength":20},"producedByParty":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Defaults to the producer of the first input"},"hsCode":{"type":["string","null"],"pattern":"^\\d{4,10}$/u"}},"required":["quantity","unitType"],"additionalProperties":false},"minItems":1,"maxItems":50},"losses":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["sawdust","bark","trim","moisture","offal","blood","bone","mortality","pulp","husk","defects","chaff","shell","fiber","kernel","empty_bunch","sludge","fatty_acids","hull","foreign_matter","other"]},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"Quantity in the unit, at most three decimals (a count is whole)."},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."}},"required":["kind","quantity","unitType"],"additionalProperties":false},"maxItems":20},"unitFactors":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"to":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"],"description":"The unit the quantity is stored in (a lot’s `unitType`). Every mass unit stores kilograms."},"ratio":{"type":"number","exclusiveMinimum":0,"maximum":1000000000}},"required":["from","to","ratio"],"additionalProperties":false},"maxItems":5,"description":"Bridges between units the record needs: one `from` is `ratio` `to` (kg per head, m³ per door). With none, a count is never compared with a mass or a volume."},"conversionFactor":{"type":["object","null"],"properties":{"value":{"type":"number","exclusiveMinimum":0,"maximum":1},"reference":{"type":"string","minLength":1,"maxLength":200,"description":"The technical study the factor comes from"}},"required":["value","reference"],"additionalProperties":false,"description":"A mill’s own conversion factor, within the template’s range. Omitted: the template’s typical yield."},"note":{"type":["string","null"],"maxLength":1000},"reference":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f]+$/u","description":"CUS-607: the company’s own number for the step (S-0388, the ERP’s production order). Unique per company among transformations: a second step with it is refused with 409. Set when recorded, never after.","examples":["T-2091"]},"claim":{"type":["object","null"],"properties":{"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"system":{"type":"string","enum":["transfer","percentage","credit","identity_preserved","segregated","mass_balance","mixed_identity_preserved"],"description":"The control system: FSC and PEFC `transfer` (PEFC: physical separation), `percentage`, `credit`; RSPO `identity_preserved`, `segregated`, `mass_balance`; Rainforest Alliance `identity_preserved`, `segregated`, `mass_balance` (not for coffee: CUS-602), `mixed_identity_preserved`; Fairtrade and RTRS `segregated`, `mass_balance`; ProTerra `identity_preserved`, `segregated`."},"productClass":{"type":["string","null"],"pattern":"^[a-z0-9][a-z0-9_:./-]{0,63}$/u","description":"The credit account’s product group (FSC) / product line (RSPO). Default: each output’s commodity and stage (`wood:product`)."}},"required":["scheme","system"],"additionalProperties":false,"description":"Compute the certification claim each output carries from the inputs’ claims, under this scheme and control system. An input not eligible under it (no claim of the scheme, a mixed identity under identity preserved) is refused with 422; a credit system is kept per site, so the step needs one."},"attachments":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"maxItems":20,"description":"Video review take 2 (N086): documents of the company recorded with the step (a photo of the sawing, the production order), uploaded first. At most 20; the record’s content hash commits to them."},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["kind","occurredAt","inputs","outputs"],"additionalProperties":false},"CustodyTransformationList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyTransformation"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyTransport":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"carrierName":{"type":["string","null"]},"vehicleId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plate":{"type":["string","null"]},"vehicleKind":{"type":["string","null"],"enum":["truck","trailer","boat","wagon","other",null]},"onFoot":{"type":"boolean"},"driverId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"origin":{"type":"object","properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"}},"required":["siteId","partyId","name","location"],"additionalProperties":false},"destination":{"type":"object","properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"}},"required":["siteId","partyId","name","location"],"additionalProperties":false},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelReason":{"type":["string","null"]},"route":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["LineString"]},"coordinates":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":2,"maxItems":2000}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON LineString (RFC 7946 §3.1.4): the road taken, [lon, lat]","format":"geojson"},"shipmentId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"weighing":{"type":"object","properties":{"grossKg":{"type":["number","null"]},"tareKg":{"type":["number","null"]},"netKg":{"type":["number","null"]},"volumeM3":{"type":["number","null"]}},"required":["grossKg","tareKg","netKg","volumeM3"],"additionalProperties":false},"balance":{"type":"object","properties":{"unit":{"type":["string","null"],"enum":["kg","cubic_meter",null]},"loadedTotal":{"type":["number","null"]},"measuredTotal":{"type":["number","null"]},"toleranceRatio":{"type":"number"},"status":{"type":["string","null"],"enum":["within_tolerance","outside_tolerance","not_measured","not_assessable",null]}},"required":["unit","loadedTotal","measuredTotal","toleranceRatio","status"],"additionalProperties":false,"description":"The loaded total against the scale, judged at loading"},"alerts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]}},"required":["code"],"additionalProperties":{},"description":"A flag the load was recorded with, never a refusal. `load_outside_tolerance` carries `loaded`, `measured`, `difference` and `unit`; `over_vehicle_capacity` carries `carried` and `capacity`; `driver_licence_expired` carries `expiredOn`; `driver_licence_category` carries `category` and `vehicleKind`; `driver_vehicle_other_carrier` carries both carriers; `vehicle_on_open_trip` carries the other `transportId`; `lot_contaminated` (a load recorded offline) carries `batchId` and `contaminationIds`; `gov_document_missing` (raised at the departure) carries the `guide`."}},"alertConfirmation":{"type":["object","null"],"properties":{"codes":{"type":"array","items":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]}},"reason":{"type":"string"},"confirmedBy":{"type":["string","null"]},"confirmedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["codes","reason","confirmedBy","confirmedAt"],"additionalProperties":false,"description":"The alerts the person loading confirmed, with their reason, who and when"},"departureCheck":{"type":["object","null"],"properties":{"alerts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]}},"required":["code"],"additionalProperties":{},"description":"A flag the load was recorded with, never a refusal. `load_outside_tolerance` carries `loaded`, `measured`, `difference` and `unit`; `over_vehicle_capacity` carries `carried` and `capacity`; `driver_licence_expired` carries `expiredOn`; `driver_licence_category` carries `category` and `vehicleKind`; `driver_vehicle_other_carrier` carries both carriers; `vehicle_on_open_trip` carries the other `transportId`; `lot_contaminated` (a load recorded offline) carries `batchId` and `contaminationIds`; `gov_document_missing` (raised at the departure) carries the `guide`."}},"confirmation":{"type":["object","null"],"properties":{"codes":{"type":"array","items":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]}},"reason":{"type":"string"},"confirmedBy":{"type":["string","null"]},"confirmedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["codes","reason","confirmedBy","confirmedAt"],"additionalProperties":false}},"required":["alerts","confirmation"],"additionalProperties":false,"description":"What the departure was checked for: the guides the goods travel under that the trip left without (`gov_document_missing` with its `guide`, `forest_guide` or `gta`), and the confirmation when the person read them. Null when the departure raised nothing, and before it."},"loadsRoot":{"type":["string","null"]},"source":{"type":"string","enum":["web","mobile","api","hardware_bridge","cron","registry_sync"]},"note":{"type":["string","null"]},"reference":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"commodity":{"type":"string"},"stage":{"type":["string","null"]},"quantity":{"type":"number"},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]}},"required":["id","batchId","lotCode","commodity","stage","quantity","unitType"],"additionalProperties":false}},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"sha256Verified":{"type":"boolean"}},"required":["id","type","createdAt","sha256Verified"],"additionalProperties":false},"description":"Transport documents filed against it (CT-e, MDF-e, GF, DOF, GTA…)"},"receiptId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The receipt that received it at its destination site, once received"},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","status","carrierPartyId","carrierName","vehicleId","plate","vehicleKind","onFoot","driverId","origin","destination","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","cancelReason","route","shipmentId","weighing","balance","alerts","alertConfirmation","departureCheck","loadsRoot","source","note","reference","createdAt","updatedAt","loads","documents","receiptId"],"additionalProperties":false},"CustodyTransportProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyTransportCreate":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit"],"description":"Where the new transport stands when the call returns. Omitted: in_transit with `actualDepartureAt`, loaded with `loads`, else planned."},"origin":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"destination":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The carrier (a party). Omitted: the vehicle’s carrier; null: the own fleet"},"vehicleId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"driverId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"route":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["LineString"]},"coordinates":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":2,"maxItems":2000}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON LineString (RFC 7946 §3.1.4): the road taken, [lon, lat]","format":"geojson"},"shipmentId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The commercial shipment (and its DDS) this leg belongs to"},"note":{"type":["string","null"],"maxLength":1000,"description":"Free text. Do not write personal data in it."},"reference":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f]+$/u","description":"CUS-607: the company’s own number for the trip (T-2091, the ERP’s invoice). Unique per company among transports: a second trip with it is refused with 409. Part of the header: set or changed while planned, fixed from `loaded` on.","examples":["T-2091"]},"loads":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"How much of the lot goes on board"}},"required":["batchId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":100},"weighing":{"type":["object","null"],"properties":{"grossKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"tareKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"netKg":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"Derived from gross − tare when both are given"},"volumeM3":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"A measured load volume (stacked logs), m³"}},"additionalProperties":false},"loadedAt":{"type":"string","format":"date-time","description":"When the lots went on board. Omitted: now"},"confirmation":{"type":["object","null"],"properties":{"codes":{"type":"array","items":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]},"maxItems":20},"reason":{"type":"string","maxLength":500}},"required":["codes","reason"],"additionalProperties":false,"description":"The alerts the person read before loading and why they loaded anyway. Sent, every alert that asks for a confirmation must be listed (409 TRANSPORT_ALERTS_CHANGED otherwise). Omitted: the load is recorded, its alerts unconfirmed and sent for review."},"location":{"type":["object","null"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"accuracyM":{"type":["number","null"],"minimum":0,"maximum":100000}},"required":["lat","lng"],"additionalProperties":false,"description":"Where the device stood when the truck was loaded (GPS)"},"actualDepartureAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["origin","destination"],"additionalProperties":false},"CustodyTransportList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyTransport"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyTransportPatch":{"type":"object","properties":{"origin":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"destination":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"carrierPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The carrier (a party). Omitted: the vehicle’s carrier; null: the own fleet"},"vehicleId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"driverId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"route":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["LineString"]},"coordinates":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]},"minItems":2,"maxItems":2000}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON LineString (RFC 7946 §3.1.4): the road taken, [lon, lat]","format":"geojson"},"shipmentId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The commercial shipment (and its DDS) this leg belongs to"},"note":{"type":["string","null"],"maxLength":1000,"description":"Free text. Do not write personal data in it."},"reference":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f]+$/u","description":"CUS-607: the company’s own number for the trip (T-2091, the ERP’s invoice). Unique per company among transports: a second trip with it is refused with 409. Part of the header: set or changed while planned, fixed from `loaded` on.","examples":["T-2091"]}},"additionalProperties":false,"description":"PATCH /v1/custody/transports/{id}: the header of a planned transport"},"CustodyTransportLoad":{"type":"object","properties":{"loads":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"How much of the lot goes on board"}},"required":["batchId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":100},"weighing":{"type":["object","null"],"properties":{"grossKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"tareKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"netKg":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"Derived from gross − tare when both are given"},"volumeM3":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"A measured load volume (stacked logs), m³"}},"additionalProperties":false},"loadedAt":{"type":"string","format":"date-time","description":"When the lots went on board. Omitted: now"},"confirmation":{"type":["object","null"],"properties":{"codes":{"type":"array","items":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]},"maxItems":20},"reason":{"type":"string","maxLength":500}},"required":["codes","reason"],"additionalProperties":false,"description":"The alerts the person read before loading and why they loaded anyway. Sent, every alert that asks for a confirmation must be listed (409 TRANSPORT_ALERTS_CHANGED otherwise). Omitted: the load is recorded, its alerts unconfirmed and sent for review."},"location":{"type":["object","null"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"accuracyM":{"type":["number","null"],"minimum":0,"maximum":100000}},"required":["lat","lng"],"additionalProperties":false,"description":"Where the device stood when the truck was loaded (GPS)"}},"required":["loads"],"additionalProperties":false,"description":"POST /v1/custody/transports/{id}/load: the lots on board and the weighing"},"CustodyTransportDepart":{"type":"object","properties":{"actualDepartureAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"confirmation":{"type":["object","null"],"properties":{"codes":{"type":"array","items":{"type":"string","enum":["load_outside_tolerance","load_not_assessable","over_vehicle_capacity","driver_missing","driver_licence_expired","driver_licence_category","driver_vehicle_other_carrier","vehicle_on_open_trip","lot_contaminated","gov_document_missing"]},"maxItems":20},"reason":{"type":"string","maxLength":500}},"required":["codes","reason"],"additionalProperties":false,"description":"The alerts the person read before recording the departure and why the truck left anyway: `gov_document_missing` when wood or cattle leave in Brazil without the DOF / GF or the GTA. Sent, every alert the departure raises must be listed (409 TRANSPORT_ALERTS_CHANGED otherwise). Omitted: the departure is recorded, its alerts unconfirmed and sent for review."}},"required":["actualDepartureAt"],"additionalProperties":false,"description":"POST /v1/custody/transports/{id}/depart"},"CustodyTransportDeliver":{"type":"object","properties":{"actualArrivalAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["actualArrivalAt"],"additionalProperties":false,"description":"POST /v1/custody/transports/{id}/deliver"},"CustodyTransportCancel":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["reason"],"additionalProperties":false,"description":"POST /v1/custody/transports/{id}/cancel"},"CustodyReceiptRecorded":{"type":"object","properties":{"receipt":{"$ref":"#/components/schemas/CustodyReceipt"},"transport":{"$ref":"#/components/schemas/CustodyTransport"}},"required":["receipt","transport"]},"CustodyReceipt":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transportId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"site":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"location":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}]}},"required":["type","coordinates"],"additionalProperties":false,"description":"GeoJSON Point (RFC 7946 §3.1.2): [lon, lat]","format":"geojson"}},"required":["siteId","name","location"],"additionalProperties":false},"receivingPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"receivedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"outcome":{"type":"string","enum":["accepted","partial","rejected"],"description":"accepted: everything that arrived; partial: part of it (say how much per lot); rejected: none of it."},"outcomeBasis":{"type":"string","enum":["operator","grading"],"description":"operator: the receiver chose the outcome; grading: a full acceptance the grading settled in part (then no reason)"},"rejectionReason":{"type":["string","null"]},"weighingSource":{"type":"string","enum":["manual","hardware_bridge"],"description":"manual: typed; hardware_bridge: taken from a scale reading"},"weighing":{"type":"object","properties":{"grossKg":{"type":["number","null"]},"tareKg":{"type":["number","null"]},"netKg":{"type":["number","null"]},"volumeM3":{"type":["number","null"]}},"required":["grossKg","tareKg","netKg","volumeM3"],"additionalProperties":false},"weighingReading":{"type":["object","null"],"properties":{"readingId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"bridgeId":{"type":"string"},"deviceSerial":{"type":"string","description":"The scale’s serial number"},"readAt":{"type":"string","format":"date-time","description":"When the scale read it"}},"required":["readingId","bridgeId","deviceSerial","readAt"],"additionalProperties":false,"description":"The scale reading a weight was taken from"},"ticketNumber":{"type":["string","null"]},"totals":{"type":"object","properties":{"unit":{"type":["string","null"],"enum":["kg","cubic_meter",null]},"sent":{"type":["number","null"]},"received":{"type":["number","null"]},"accepted":{"type":["number","null"]}},"required":["unit","sent","received","accepted"],"additionalProperties":false,"description":"When every lot is on one scale: kg for a mass, m³ for a volume"},"divergenceStatus":{"type":"string","enum":["within_tolerance","outside_tolerance"]},"alerts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["line_outside_tolerance","weight_outside_tolerance","departure_not_recorded","grading_outside_standard"]}},"required":["code"],"additionalProperties":{},"description":"A flag the receipt was recorded with, never a refusal. `line_outside_tolerance` carries `batchId`, `sent`, `received`, `difference`, `direction` (loss | gain), `pct` and the band; `weight_outside_tolerance` the same for the truck’s weight; `departure_not_recorded` says the load time stands for the departure; `grading_outside_standard` carries `batchId`, `received`, `graded` (what the grading allows) and the `keys` past their thresholds: a quality settlement, not sent to the compliance queue."}},"attachments":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"source":{"type":"string","enum":["web","mobile","api","hardware_bridge","cron","registry_sync"]},"note":{"type":["string","null"]},"linesRoot":{"type":"string"},"contentSha256":{"type":"string"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"sentQuantity":{"type":"number"},"receivedQuantity":{"type":"number"},"acceptedQuantity":{"type":"number"},"placedQuantity":{"type":"number","description":"Now at the receiving site"},"returnedQuantity":{"type":"number","description":"Back with the sender, at the origin"},"transitLoss":{"type":"number","description":"Sent − received; negative for a gain"},"band":{"type":"object","properties":{"maxLossPct":{"type":"number"},"maxGainPct":{"type":"number"},"basis":{"type":"string","enum":["template_stage","template_stage_candidates","count_exact","default"]},"stage":{"type":["string","null"]},"templateVersion":{"type":["string","null"]}},"required":["maxLossPct","maxGainPct","basis","stage","templateVersion"],"additionalProperties":false,"description":"The directional tolerance the line was judged with"},"grading":{"type":["object","null"],"properties":{"stage":{"type":["string","null"]},"templateVersion":{"type":"string"},"measures":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"number"},"limit":{"type":"number"},"direction":{"type":"string","enum":["max","min"]},"deduction":{"type":"string","enum":["dry_matter","content_ratio","excess_share"]},"outside":{"type":"boolean"}},"required":["key","value","limit","direction","deduction","outside"],"additionalProperties":false}},"accepted":{"type":"number","description":"What the grading allows of what arrived"}},"required":["stage","templateVersion","measures","accepted"],"additionalProperties":false,"description":"The grading taken on arrival, as judged; null when none was"},"divergenceStatus":{"type":"string","enum":["within_tolerance","outside_tolerance"]},"quantitySource":{"type":"string","enum":["manual","hardware_bridge"],"description":"manual: typed; hardware_bridge: taken from a scale reading"},"reading":{"type":["object","null"],"properties":{"readingId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"bridgeId":{"type":"string"},"deviceSerial":{"type":"string","description":"The scale’s serial number"},"readAt":{"type":"string","format":"date-time","description":"When the scale read it"}},"required":["readingId","bridgeId","deviceSerial","readAt"],"additionalProperties":false,"description":"The scale reading a weight was taken from"}},"required":["id","batchId","lotCode","unitType","sentQuantity","receivedQuantity","acceptedQuantity","placedQuantity","returnedQuantity","transitLoss","band","grading","divergenceStatus","quantitySource","reading"],"additionalProperties":false}},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s custom values, keyed by field key (retired fields included). Present only for a caller holding `custom-fields.read` (sessions always) while custom fields are on for the workspace; absent otherwise, never empty for lack of the scope. Never part of the record’s content hash or proof."}},"required":["id","transportId","site","receivingPartyId","receivedAt","outcome","outcomeBasis","rejectionReason","weighingSource","weighing","weighingReading","ticketNumber","totals","divergenceStatus","alerts","attachments","source","note","linesRoot","contentSha256","createdAt","lines"],"additionalProperties":false},"CustodyReceiptProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyReceiptRecord":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transportId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"receivedAt":{"type":"string","format":"date-time","description":"When the truck was received. Omitted: now"},"outcome":{"type":"string","enum":["accepted","partial","rejected"],"description":"accepted: everything that arrived; partial: part of it (say how much per lot); rejected: none of it."},"lines":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"receivedQuantity":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"What arrived of the lot, typed (0 when nothing did). Leave out when `readingId` names the scale reading it is"},"readingId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"A scale reading (from `POST /v1/custody/bridge/events`) whose net, in kg, is what arrived of this lot. Only for a lot counted in a mass; a stable reading of a bridge at the receiving site, not taken by another receipt"},"acceptedQuantity":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"What was accepted of it. Required for a partial acceptance (unless its grading settles it); implied otherwise"},"grading":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","maxLength":40,"pattern":"^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/u"},"value":{"type":"number","minimum":0,"maximum":100,"description":"The measurement, in percent, at most two decimals"}},"required":["key","value"],"additionalProperties":false},"maxItems":10,"description":"Measurements taken on arrival: the keys the lot’s stage grades (`GET /v1/custody/templates`). One past its threshold settles part of the line."}},"required":["batchId"],"additionalProperties":false},"minItems":1,"maxItems":100,"description":"One line per lot on board: every lot, and only those"},"weighing":{"type":["object","null"],"properties":{"readingId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"A scale reading the truck’s gross, tare and net are taken from (then do not type them). The volume may still be typed"},"grossKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"tareKg":{"type":["number","null"],"minimum":0,"maximum":1000000000},"netKg":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"Derived from gross − tare when both are given"},"volumeM3":{"type":["number","null"],"minimum":0,"maximum":1000000000,"description":"A measured load volume, m³"}},"additionalProperties":false},"ticketNumber":{"type":["string","null"],"minLength":1,"maxLength":100,"description":"The weighbridge ticket’s number"},"rejectionReason":{"type":["string","null"],"minLength":1,"maxLength":500,"description":"Why part or all of it was refused. Required for partial and rejected. Do not write personal data in it."},"note":{"type":["string","null"],"maxLength":1000,"description":"Free text. Do not write personal data in it."},"attachments":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"maxItems":20,"description":"Documents (photos, the ticket’s scan) already filed against the transport"},"location":{"type":["object","null"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}},"required":["lat","lng"],"additionalProperties":false,"description":"Where the device was. Omitted: the site’s point"},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["transportId","outcome","lines"],"additionalProperties":false},"CustodyReceiptList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyReceipt"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyChainVerification":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"ok":{"type":"boolean","description":"No record differs, and the whole chain was read. Departures do not count."},"checkedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lots":{"type":"integer","minimum":1,"description":"Lots in the upstream chain."},"records":{"type":"integer","minimum":0,"description":"Records checked."},"unhashed":{"type":"integer","minimum":0,"description":"Records written before fingerprints existed, which cannot be checked. Never counted as checked."},"truncated":{"type":"boolean","description":"The chain is larger than one check reads; the answer covers part of it."},"root":{"type":["string","null"],"format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"leafCount":{"type":"integer","minimum":0},"seal":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"The fingerprint over every record the seal covers."},"leafCount":{"type":"integer","minimum":1},"lotCount":{"type":"integer","minimum":1},"unhashedCount":{"type":"integer","minimum":0,"description":"Records of the chain written before fingerprints existed: not covered."},"sealedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"supersedesSealId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"current":{"type":"boolean","description":"The chain still matches this seal; false once it has grown or changed."}},"required":["id","root","leafCount","lotCount","unhashedCount","sealedAt","supersedesSealId","current"],"description":"The lot's live chain seal."},"divergences":{"type":"array","items":{"type":"object","properties":{"recordType":{"type":"string","enum":["event","transformation","transformation_input","transformation_output","transformation_loss","transport","transport_load","receipt","receipt_line","document","custody_seal"],"description":"The kind of record that differs; `custody_seal` when it is the seal itself."},"id":{"type":"string","minLength":1,"description":"The id of the record that differs."},"where":{"type":"string","enum":["row","ledger","chain","seal"],"description":"`row`: the record no longer matches the fingerprint stored with it. `ledger`: it does not match the fingerprint the audit trail recorded. `chain`: the audit-trail entry about it no longer links to the entries around it. `seal`: it is not what the lot’s last seal covered."},"reason":{"type":"string","enum":["content_changed","missing","hash_removed","children_changed","ledger_mismatch","not_attested","self_hash_mismatch","prev_hash_mismatch","seal_mismatch","signature_mismatch"],"description":"`content_changed`: its content changed after it was written. `missing`: the audit trail or the seal names it and it no longer exists at all. `hash_removed`: its stored fingerprint was removed. `children_changed`: the lines of a transformation, a transport or a receipt are not the ones it recorded. `ledger_mismatch`: the audit trail recorded another fingerprint. `not_attested`: no audit-trail entry records it. `self_hash_mismatch` / `prev_hash_mismatch`: the audit-trail entry about it was altered. `seal_mismatch`: it differs from what the seal covered. `signature_mismatch`: an event recorded as signed on the device whose device signature no longer holds over the event as it is now."},"expected":{"type":["string","null"],"description":"The fingerprint the record should have (stored, recorded or sealed)."},"actual":{"type":["string","null"],"description":"The fingerprint it has now; null when it no longer exists."},"ledgerEventId":{"type":["string","null"],"description":"The audit-trail entry involved, when there is one."}},"required":["recordType","id","where","reason","expected","actual","ledgerEventId"],"description":"One record of the chain that does not match."},"description":"Records that do not match. Each one blocks sealing."},"departures":{"type":"array","items":{"type":"object","properties":{"recordType":{"type":"string","enum":["event","transformation","transformation_input","transformation_output","transformation_loss","transport","transport_load","receipt","receipt_line","document"]},"id":{"type":"string","minLength":1},"reason":{"type":"string","enum":["removed","left_chain"],"description":"`removed`: the record was deleted through the application (a document removed, say). `left_chain`: the record still exists, but the chain no longer reaches it (an upstream lot whose link was removed before either lot entered custody). Each is listed only when the audit trail records that act after the seal; a record that left the chain without it is a divergence."},"sealed":{"type":"string","description":"The fingerprint the seal covered."},"sealId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The seal that covered it."}},"required":["recordType","id","reason","sealed","sealId"],"description":"A record the last seal covered that is no longer part of the chain, without being altered. It does not block sealing: sealing again covers the chain as it is now."}},"signatures":{"type":"object","properties":{"signed":{"type":"integer","minimum":0,"description":"Events the phone signed."},"verified":{"type":"integer","minimum":0,"description":"Signed on the device: recorded as verified, and still verifying against the event as it is now."},"flagged":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","minLength":1},"verdict":{"type":"string","enum":["bad_signature","photos_mismatch","unknown_key","revoked_key"]}},"required":["eventId","verdict"]},"description":"Events whose signature did not hold when they arrived, kept and flagged: `bad_signature` (the event is not what the phone signed), `photos_mismatch` (the files are not the ones signed), `unknown_key` (no such key of this user here), `revoked_key` (the key was revoked first)."}},"required":["signed","verified","flagged"],"description":"The device signatures of the chain's events."}},"required":["batchId","ok","checkedAt","lots","records","unhashed","truncated","root","leafCount","seal","divergences","departures","signatures"],"description":"The result of checking a lot's chain of custody."},"CustodyIntegrityProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"verification":{"$ref":"#/components/schemas/CustodyChainVerification"}},"required":["type","title","status","code"]},"CustodyChainSealResult":{"type":"object","properties":{"outcome":{"type":"string","enum":["sealed","unchanged","empty"],"description":"`sealed`: a new seal was written. `unchanged`: the live seal already covers the chain. `empty`: the lot has no fingerprinted record upstream, so there is nothing to seal."},"seal":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"The fingerprint over every record the seal covers."},"leafCount":{"type":"integer","minimum":1},"lotCount":{"type":"integer","minimum":1},"unhashedCount":{"type":"integer","minimum":0,"description":"Records of the chain written before fingerprints existed: not covered."},"sealedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"supersedesSealId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"current":{"type":"boolean","description":"The chain still matches this seal; false once it has grown or changed."}},"required":["id","root","leafCount","lotCount","unhashedCount","sealedAt","supersedesSealId","current"],"description":"The lot's live chain seal."},"verification":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"ok":{"type":"boolean","description":"No record differs, and the whole chain was read. Departures do not count."},"checkedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lots":{"type":"integer","minimum":1,"description":"Lots in the upstream chain."},"records":{"type":"integer","minimum":0,"description":"Records checked."},"unhashed":{"type":"integer","minimum":0,"description":"Records written before fingerprints existed, which cannot be checked. Never counted as checked."},"truncated":{"type":"boolean","description":"The chain is larger than one check reads; the answer covers part of it."},"root":{"type":["string","null"],"format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"leafCount":{"type":"integer","minimum":0},"seal":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"The fingerprint over every record the seal covers."},"leafCount":{"type":"integer","minimum":1},"lotCount":{"type":"integer","minimum":1},"unhashedCount":{"type":"integer","minimum":0,"description":"Records of the chain written before fingerprints existed: not covered."},"sealedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"supersedesSealId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"current":{"type":"boolean","description":"The chain still matches this seal; false once it has grown or changed."}},"required":["id","root","leafCount","lotCount","unhashedCount","sealedAt","supersedesSealId","current"],"description":"The lot's live chain seal."},"divergences":{"type":"array","items":{"type":"object","properties":{"recordType":{"type":"string","enum":["event","transformation","transformation_input","transformation_output","transformation_loss","transport","transport_load","receipt","receipt_line","document","custody_seal"],"description":"The kind of record that differs; `custody_seal` when it is the seal itself."},"id":{"type":"string","minLength":1,"description":"The id of the record that differs."},"where":{"type":"string","enum":["row","ledger","chain","seal"],"description":"`row`: the record no longer matches the fingerprint stored with it. `ledger`: it does not match the fingerprint the audit trail recorded. `chain`: the audit-trail entry about it no longer links to the entries around it. `seal`: it is not what the lot’s last seal covered."},"reason":{"type":"string","enum":["content_changed","missing","hash_removed","children_changed","ledger_mismatch","not_attested","self_hash_mismatch","prev_hash_mismatch","seal_mismatch","signature_mismatch"],"description":"`content_changed`: its content changed after it was written. `missing`: the audit trail or the seal names it and it no longer exists at all. `hash_removed`: its stored fingerprint was removed. `children_changed`: the lines of a transformation, a transport or a receipt are not the ones it recorded. `ledger_mismatch`: the audit trail recorded another fingerprint. `not_attested`: no audit-trail entry records it. `self_hash_mismatch` / `prev_hash_mismatch`: the audit-trail entry about it was altered. `seal_mismatch`: it differs from what the seal covered. `signature_mismatch`: an event recorded as signed on the device whose device signature no longer holds over the event as it is now."},"expected":{"type":["string","null"],"description":"The fingerprint the record should have (stored, recorded or sealed)."},"actual":{"type":["string","null"],"description":"The fingerprint it has now; null when it no longer exists."},"ledgerEventId":{"type":["string","null"],"description":"The audit-trail entry involved, when there is one."}},"required":["recordType","id","where","reason","expected","actual","ledgerEventId"],"description":"One record of the chain that does not match."},"description":"Records that do not match. Each one blocks sealing."},"departures":{"type":"array","items":{"type":"object","properties":{"recordType":{"type":"string","enum":["event","transformation","transformation_input","transformation_output","transformation_loss","transport","transport_load","receipt","receipt_line","document"]},"id":{"type":"string","minLength":1},"reason":{"type":"string","enum":["removed","left_chain"],"description":"`removed`: the record was deleted through the application (a document removed, say). `left_chain`: the record still exists, but the chain no longer reaches it (an upstream lot whose link was removed before either lot entered custody). Each is listed only when the audit trail records that act after the seal; a record that left the chain without it is a divergence."},"sealed":{"type":"string","description":"The fingerprint the seal covered."},"sealId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The seal that covered it."}},"required":["recordType","id","reason","sealed","sealId"],"description":"A record the last seal covered that is no longer part of the chain, without being altered. It does not block sealing: sealing again covers the chain as it is now."}},"signatures":{"type":"object","properties":{"signed":{"type":"integer","minimum":0,"description":"Events the phone signed."},"verified":{"type":"integer","minimum":0,"description":"Signed on the device: recorded as verified, and still verifying against the event as it is now."},"flagged":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","minLength":1},"verdict":{"type":"string","enum":["bad_signature","photos_mismatch","unknown_key","revoked_key"]}},"required":["eventId","verdict"]},"description":"Events whose signature did not hold when they arrived, kept and flagged: `bad_signature` (the event is not what the phone signed), `photos_mismatch` (the files are not the ones signed), `unknown_key` (no such key of this user here), `revoked_key` (the key was revoked first)."}},"required":["signed","verified","flagged"],"description":"The device signatures of the chain's events."}},"required":["batchId","ok","checkedAt","lots","records","unhashed","truncated","root","leafCount","seal","divergences","departures","signatures"],"description":"The result of checking a lot's chain of custody."}},"required":["outcome","seal","verification"],"description":"Sealing a lot's chain of custody."},"LedgerDayList":{"type":"object","properties":{"days":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"firstChainSeq":{"type":"integer","minimum":1},"lastChainSeq":{"type":"integer","minimum":1},"leafCount":{"type":"integer","minimum":1},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["day","firstChainSeq","lastChainSeq","leafCount","root"],"description":"One day of the workspace audit trail: the events it covers and their fingerprint."},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/LedgerDaySummary"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"LedgerDaySummary":{"type":"object","properties":{"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"firstChainSeq":{"type":"integer","minimum":1},"lastChainSeq":{"type":"integer","minimum":1},"leafCount":{"type":"integer","minimum":1},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["day","firstChainSeq","lastChainSeq","leafCount","root"],"description":"One day of the workspace audit trail: the events it covers and their fingerprint."},"LedgerTimestampProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"LedgerDayExport":{"type":"object","properties":{"format":{"type":"string","enum":["origonex.ledger-day-timestamp"]},"version":{"type":"number","enum":[1]},"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"chain":{"type":"object","properties":{"chainKey":{"type":"string"},"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"firstChainSeq":{"type":"integer","minimum":1},"lastChainSeq":{"type":"integer","minimum":1},"leafCount":{"type":"integer","minimum":1},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"leafVersion":{"type":"number","enum":[2],"description":"Absent (v1): the day leaf names the chain and its counts. 2: it commits to them with `salt` (runbook §\"The trees\")."},"salt":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["chainKey","day","firstChainSeq","lastChainSeq","leafCount","root"]},"leaves":{"type":"array","items":{"type":"object","properties":{"chainSeq":{"type":"integer","minimum":1},"selfHash":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"event":{"type":"object","properties":{"prevHash":{"type":["string","null"],"format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"tenantId":{"type":["string","null"]},"kind":{"type":"string"},"actorUserId":{"type":["string","null"]},"actorEmail":{"type":["string","null"]},"subjectType":{"type":["string","null"]},"subjectId":{"type":["string","null"]},"payload":{},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["prevHash","tenantId","kind","actorUserId","actorEmail","subjectType","subjectId","createdAt"],"description":"The nine fields an audit-trail entry’s fingerprint is computed from: SHA-256 over their RFC 8785 JSON form."}},"required":["chainSeq","selfHash"]}},"dayLeaf":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"dayProof":{"type":"array","items":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"dayRoot":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"timestamp":{"type":["object","null"],"properties":{"imprint":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"authority":{"type":"string"},"url":{"type":"string"},"genTime":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"serialNumber":{"type":"string"},"token":{"type":"string","description":"The RFC 3161 time-stamp token (CMS), DER, base64."},"certificates":{"type":"string","description":"The authority's signing certificate up to its root, PEM."}},"required":["imprint","authority","url","genTime","serialNumber","token","certificates"]}},"required":["format","version","day","chain","leaves","dayLeaf","dayProof","dayRoot","timestamp"],"description":"Everything needed to check one day of the audit trail without Origonex: the entries, the fingerprint of the day, the path from it to the fingerprint of every workspace’s day, and the time-stamp token an independent authority signed over it. Check it with `scripts/verify-timestamp.mts`."},"RecordInclusionResult":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["open"]},"ledgerEventId":{"type":"string"},"chainSeq":{"type":"integer","minimum":1}},"required":["status","ledgerEventId","chainSeq"]},{"type":"object","properties":{"status":{"type":"string","enum":["pending","stamped"]},"ledgerEventId":{"type":"string"},"chainSeq":{"type":"integer","minimum":1},"proof":{"type":"object","properties":{"format":{"type":"string","enum":["origonex.ledger-record-inclusion"]},"version":{"type":"number","enum":[2]},"audience":{"type":"string","enum":["workspace","public"]},"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"record":{"anyOf":[{"type":"object","properties":{"ledgerEventId":{"type":"string"},"chainSeq":{"type":"integer","minimum":1},"selfHash":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"event":{"type":"object","properties":{"prevHash":{"type":["string","null"],"format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"tenantId":{"type":["string","null"]},"kind":{"type":"string"},"actorUserId":{"type":["string","null"]},"actorEmail":{"type":["string","null"]},"subjectType":{"type":["string","null"]},"subjectId":{"type":["string","null"]},"payload":{},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["prevHash","tenantId","kind","actorUserId","actorEmail","subjectType","subjectId","createdAt"],"description":"The nine fields an audit-trail entry’s fingerprint is computed from: SHA-256 over their RFC 8785 JSON form."}},"required":["ledgerEventId","chainSeq","selfHash"]},{"type":"object","properties":{"selfHash":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["selfHash"],"additionalProperties":false}]},"chainProof":{"type":"array","items":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"chain":{"anyOf":[{"type":"object","properties":{"chainKey":{"type":"string"},"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"firstChainSeq":{"type":"integer","minimum":1},"lastChainSeq":{"type":"integer","minimum":1},"leafCount":{"type":"integer","minimum":1},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"leafVersion":{"type":"number","enum":[2],"description":"Absent (v1): the day leaf names the chain and its counts. 2: it commits to them with `salt` (runbook §\"The trees\")."},"salt":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["chainKey","day","firstChainSeq","lastChainSeq","leafCount","root"]},{"type":"object","properties":{"leafVersion":{"type":"number","enum":[2]},"day":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"root":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"commitment":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"required":["leafVersion","day","root","commitment"]}]},"dayLeaf":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"dayProof":{"type":"array","items":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"}},"dayRoot":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"timestamp":{"type":["object","null"],"properties":{"imprint":{"type":"string","format":"hex32","pattern":"^[0-9a-f]{64}$/u","description":"64-char lowercase hex (32 bytes): SHA-256 digest"},"authority":{"type":"string"},"url":{"type":"string"},"genTime":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"serialNumber":{"type":"string"},"token":{"type":"string","description":"The RFC 3161 time-stamp token (CMS), DER, base64."},"certificates":{"type":"string","description":"The authority's signing certificate up to its root, PEM."}},"required":["imprint","authority","url","genTime","serialNumber","token","certificates"]}},"required":["format","version","audience","day","record","chainProof","chain","dayLeaf","dayProof","dayRoot","timestamp"],"description":"Everything needed to check that one audit-trail entry is in a day an independent authority timestamped, without the other entries: the entry (its content, unless the copy is public), the path from its fingerprint to the fingerprint of its day, the path on to the fingerprint of every workspace’s day, and the authority’s time-stamp token over it. Check it with `scripts/verify-timestamp.mts --record`."}},"required":["status","ledgerEventId","chainSeq","proof"]}]},"RecordProofList":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","properties":{"ledgerEventId":{"type":"string"},"kind":{"type":"string"},"subjectType":{"type":["string","null"]},"subjectId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"chainSeq":{"type":"integer","minimum":1},"day":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"status":{"type":"string","enum":["open","pending","stamped"],"description":"`open`: the entry’s day is not closed yet. `pending`: closed, the authority has not answered yet. `stamped`: the proof carries the authority’s token."}},"required":["ledgerEventId","kind","subjectType","subjectId","createdAt","chainSeq","day","status"]}}},"required":["records"]},"TagRollIssueResponse":{"type":"object","properties":{"status":{"type":"string","enum":["created","replayed"]},"roll":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"labelCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"counts":{"type":"object","properties":{"free":{"type":"integer"},"used":{"type":"integer"},"withdrawn":{"type":"integer"}},"required":["free","used","withdrawn"],"additionalProperties":false},"labels":{"type":"array","items":{"type":"object","properties":{"tagId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"seq":{"type":"integer","minimum":1,"description":"Its place on the roll, from 1."},"value":{"type":"string","description":"The code the QR carries (`OXL-…`)."},"state":{"type":"string","enum":["free","used","withdrawn"],"description":"`free`: on no lot yet. `used`: linked to a live lot. `withdrawn`: revoked, never to be linked."},"batch":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"}},"required":["id","lotCode"]}},"required":["tagId","seq","value","state","batch"],"additionalProperties":false}}},"required":["id","labelCount","createdAt","counts","labels"],"additionalProperties":false}},"required":["status","roll"],"additionalProperties":false},"TagRollProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"TagRollIssueRequest":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":500,"description":"How many labels the roll holds, 1 to 500."},"requestId":{"type":"string","minLength":8,"maxLength":64,"description":"Idempotency key: a retry with the same key and count answers the same roll."}},"required":["count","requestId"],"additionalProperties":false},"TagRollList":{"type":"object","properties":{"rolls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"labelCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"counts":{"type":"object","properties":{"free":{"type":"integer"},"used":{"type":"integer"},"withdrawn":{"type":"integer"}},"required":["free","used","withdrawn"],"additionalProperties":false}},"required":["id","labelCount","createdAt","counts"],"additionalProperties":false},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/TagRollSummary"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"TagRollSummary":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"labelCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"counts":{"type":"object","properties":{"free":{"type":"integer"},"used":{"type":"integer"},"withdrawn":{"type":"integer"}},"required":["free","used","withdrawn"],"additionalProperties":false}},"required":["id","labelCount","createdAt","counts"],"additionalProperties":false},"TagRoll":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"labelCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"counts":{"type":"object","properties":{"free":{"type":"integer"},"used":{"type":"integer"},"withdrawn":{"type":"integer"}},"required":["free","used","withdrawn"],"additionalProperties":false},"labels":{"type":"array","items":{"type":"object","properties":{"tagId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"seq":{"type":"integer","minimum":1,"description":"Its place on the roll, from 1."},"value":{"type":"string","description":"The code the QR carries (`OXL-…`)."},"state":{"type":"string","enum":["free","used","withdrawn"],"description":"`free`: on no lot yet. `used`: linked to a live lot. `withdrawn`: revoked, never to be linked."},"batch":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"}},"required":["id","lotCode"]}},"required":["tagId","seq","value","state","batch"],"additionalProperties":false}}},"required":["id","labelCount","createdAt","counts","labels"],"additionalProperties":false},"SupplyLinkList":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["tenantId","name","slug","country"],"additionalProperties":false},"importer":{"type":"object","properties":{"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["tenantId","name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"requestNote":{"type":["string","null"]},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"scope":{"type":"object","properties":{"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"}},"required":["batchIds","fields","shareDds"],"additionalProperties":false},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endReason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","importer","requestedAt","requestNote","grantedAt","acceptedAt","scope","endedAt","endReason","createdAt","updatedAt"],"additionalProperties":false},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/SupplyLink"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"SupplyLink":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["tenantId","name","slug","country"],"additionalProperties":false},"importer":{"type":"object","properties":{"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["tenantId","name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"requestNote":{"type":["string","null"]},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"scope":{"type":"object","properties":{"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"}},"required":["batchIds","fields","shareDds"],"additionalProperties":false},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endReason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","importer","requestedAt","requestNote","grantedAt","acceptedAt","scope","endedAt","endReason","createdAt","updatedAt"],"additionalProperties":false},"SupplyLinkProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"SupplyLinkOffer":{"type":"object","properties":{"importerSlug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-]*$/u","description":"The other company’s workspace handle (its slug)."},"scope":{"type":"object","properties":{"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"maxItems":500,"description":"The lots shared. Nothing is shared by default."},"fields":{"type":"array","items":{"type":"string","enum":["origin.country","origin.region","origin.municipality","origin.plotMap","origin.coordinatesExact","origin.coordinatesRounded","origin.producerName","origin.area","chain.stages","transport.plate","transport.driver","transport.carrier","transport.route","transport.weights","receipt.operator","receipt.weights","transformation.site","transformation.yield","transformation.losses","event.operator","event.location","documents.list","documents.files","certificates.list","integrity.proof","integrity.recordProof","unit.serial","certification.claim","origin.contributors","custom.fields"]},"maxItems":64,"description":"The fields the importer may see on those lots, within what the lot’s visibility policy opens to importers, never more. Omitted: the conservative default (country, producer, stages, weights, certificates, integrity proof)."},"shareDds":{"type":"boolean","default":false,"description":"Share the due-diligence statements that cover those lots. Off by default."}},"required":["batchIds"],"additionalProperties":false}},"required":["importerSlug","scope"],"additionalProperties":false},"SupplyLinkGrant":{"type":"object","properties":{"scope":{"type":"object","properties":{"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"maxItems":500,"description":"The lots shared. Nothing is shared by default."},"fields":{"type":"array","items":{"type":"string","enum":["origin.country","origin.region","origin.municipality","origin.plotMap","origin.coordinatesExact","origin.coordinatesRounded","origin.producerName","origin.area","chain.stages","transport.plate","transport.driver","transport.carrier","transport.route","transport.weights","receipt.operator","receipt.weights","transformation.site","transformation.yield","transformation.losses","event.operator","event.location","documents.list","documents.files","certificates.list","integrity.proof","integrity.recordProof","unit.serial","certification.claim","origin.contributors","custom.fields"]},"maxItems":64,"description":"The fields the importer may see on those lots, within what the lot’s visibility policy opens to importers, never more. Omitted: the conservative default (country, producer, stages, weights, certificates, integrity proof)."},"shareDds":{"type":"boolean","default":false,"description":"Share the due-diligence statements that cover those lots. Off by default."}},"required":["batchIds"],"additionalProperties":false}},"required":["scope"],"additionalProperties":false},"SupplyLinkEnd":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Why, for the producer’s own record. Never shown to the importer’s ledger."}},"additionalProperties":false},"ImporterSupplyLink":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lotCount":{"type":"integer","minimum":0},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","requestedAt","grantedAt","acceptedAt","endedAt","lotCount","fields","shareDds","updatedAt"],"additionalProperties":false},"SupplyLinkRequest":{"type":"object","properties":{"producerSlug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-]*$/u","description":"The other company’s workspace handle (its slug)."},"note":{"type":"string","maxLength":500}},"required":["producerSlug"],"additionalProperties":false},"SupplyLinkAnswer":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Why the offer is declined, for the importer’s own record (kept as a hash in its ledger)."}},"additionalProperties":false},"ImporterSupplyLinkList":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lotCount":{"type":"integer","minimum":0},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","requestedAt","grantedAt","acceptedAt","endedAt","lotCount","fields","shareDds","updatedAt"],"additionalProperties":false},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lotCount":{"type":"integer","minimum":0},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","requestedAt","grantedAt","acceptedAt","endedAt","lotCount","fields","shareDds","updatedAt"],"additionalProperties":false},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"ImporterSharedLotList":{"type":"object","properties":{"lots":{"type":"array","items":{"type":"object","properties":{"linkId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"producer":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"],"additionalProperties":false},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"visibleFields":{"type":"array","items":{"type":"string"}},"record":{"type":"object","additionalProperties":{}}},"required":["linkId","producer","batchId","visibleFields","record"],"additionalProperties":false}}},"required":["lots"]},"CustodyContaminationTraceResult":{"type":"object","properties":{"replayed":{"type":"boolean","description":"The source already had an open flag for this reason: it was traced again rather than flagged twice."},"contamination":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["plot","certificate"],"description":"What was found bad: a plot of land, or a certificate."},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"label":{"type":["string","null"],"description":"The plot's name, or the certifier and certificate number."}},"required":["kind","id","label"]},"sourceSubject":{"type":["object","null"],"properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"description":"For a certificate: what it certifies, as it was when flagged."},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"note":{"type":["string","null"]},"status":{"type":"string","enum":["open","lifted"]},"raisedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"traceDepthLimit":{"type":"integer"},"traceTruncated":{"type":"boolean","description":"The last walk reached its depth or size limit: something further down may be affected and not marked."},"lastTracedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftReason":{"type":["string","null"]},"contentSha256":{"type":"string"},"counts":{"type":"object","properties":{"plot":{"type":"integer"},"batch":{"type":"integer"},"transformation":{"type":"integer"},"shipment":{"type":"integer"},"dds":{"type":"integer"}},"additionalProperties":false}},"required":["id","source","sourceSubject","reason","note","status","raisedAt","traceDepthLimit","traceTruncated","lastTracedAt","liftedAt","liftReason","contentSha256","counts"]},"added":{"type":"object","properties":{"plot":{"type":"integer"},"batch":{"type":"integer"},"transformation":{"type":"integer"},"shipment":{"type":"integer"},"dds":{"type":"integer"}},"additionalProperties":false,"description":"Marks this call wrote."},"truncated":{"type":"boolean"}},"required":["replayed","contamination","added","truncated"]},"CustodyContaminationProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyContaminationFlag":{"type":"object","properties":{"source":{"type":"object","properties":{"kind":{"type":"string","enum":["plot","certificate"],"description":"What was found bad: a plot of land, or a certificate."},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["kind","id"],"additionalProperties":false},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"note":{"type":"string","maxLength":1000,"description":"What was found, in a sentence (required for `other`). Stored with the flag; do not write personal data in it."}},"required":["source","reason"],"additionalProperties":false},"CustodyContaminationList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyContamination"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyContamination":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["plot","certificate"],"description":"What was found bad: a plot of land, or a certificate."},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"label":{"type":["string","null"],"description":"The plot's name, or the certifier and certificate number."}},"required":["kind","id","label"]},"sourceSubject":{"type":["object","null"],"properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"description":"For a certificate: what it certifies, as it was when flagged."},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"note":{"type":["string","null"]},"status":{"type":"string","enum":["open","lifted"]},"raisedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"traceDepthLimit":{"type":"integer"},"traceTruncated":{"type":"boolean","description":"The last walk reached its depth or size limit: something further down may be affected and not marked."},"lastTracedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftReason":{"type":["string","null"]},"contentSha256":{"type":"string"},"counts":{"type":"object","properties":{"plot":{"type":"integer"},"batch":{"type":"integer"},"transformation":{"type":"integer"},"shipment":{"type":"integer"},"dds":{"type":"integer"}},"additionalProperties":false}},"required":["id","source","sourceSubject","reason","note","status","raisedAt","traceDepthLimit","traceTruncated","lastTracedAt","liftedAt","liftReason","contentSha256","counts"]},"CustodyContaminationDetail":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["plot","certificate"],"description":"What was found bad: a plot of land, or a certificate."},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"label":{"type":["string","null"],"description":"The plot's name, or the certifier and certificate number."}},"required":["kind","id","label"]},"sourceSubject":{"type":["object","null"],"properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"description":"For a certificate: what it certifies, as it was when flagged."},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"note":{"type":["string","null"]},"status":{"type":"string","enum":["open","lifted"]},"raisedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"traceDepthLimit":{"type":"integer"},"traceTruncated":{"type":"boolean","description":"The last walk reached its depth or size limit: something further down may be affected and not marked."},"lastTracedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"liftReason":{"type":["string","null"]},"contentSha256":{"type":"string"},"counts":{"type":"object","properties":{"plot":{"type":"integer"},"batch":{"type":"integer"},"transformation":{"type":"integer"},"shipment":{"type":"integer"},"dds":{"type":"integer"}},"additionalProperties":false},"affected":{"type":"array","items":{"type":"object","properties":{"subjectType":{"type":"string","enum":["plot","batch","transformation","shipment","dds","transport"]},"subjectId":{"type":"string"},"depth":{"type":"integer","description":"Steps from the source (0: named by it directly)."},"viaBatchId":{"type":["string","null"]},"viaTransformationId":{"type":["string","null"]},"label":{"type":["string","null"]},"state":{"type":["string","null"]}},"required":["subjectType","subjectId","depth","viaBatchId","viaTransformationId","label","state"]}},"affectedTruncated":{"type":"boolean"}},"required":["id","source","sourceSubject","reason","note","status","raisedAt","traceDepthLimit","traceTruncated","lastTracedAt","liftedAt","liftReason","contentSha256","counts","affected","affectedTruncated"]},"CustodyContaminationLift":{"type":"object","properties":{"reason":{"type":"string","minLength":3,"maxLength":1000,"description":"Why the source is no longer considered bad (a field visit, a reinstatement)."}},"required":["reason"],"additionalProperties":false},"CustodyContaminationMitigation":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"contaminationId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string","enum":["batch","shipment","plot"]},"id":{"type":"string"}},"required":["type","id"]},"note":{"type":"string"},"recordedBy":{"type":["string","null"],"description":"The user id of who recorded it."},"recordedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"contentSha256":{"type":"string"}},"required":["id","contaminationId","subject","note","recordedBy","recordedAt","contentSha256"]},"CustodyContaminationMitigate":{"type":"object","properties":{"subject":{"type":"object","properties":{"type":{"type":"string","enum":["batch","shipment","plot"]},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false,"description":"The lot, shipment or plot whose DDS the flag blocks: the subject `dds.issue` names."},"note":{"type":"string","minLength":20,"maxLength":2000,"description":"What was done so the risk is negligible for this subject (a field visit, a laboratory result, a segregation). At least 20 characters. Stored with the note and never put in the audit trail; do not write personal data in it."}},"required":["subject","note"],"additionalProperties":false},"CustodyContaminationMitigationList":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"contaminationId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string","enum":["batch","shipment","plot"]},"id":{"type":"string"}},"required":["type","id"]},"note":{"type":"string"},"recordedBy":{"type":["string","null"],"description":"The user id of who recorded it."},"recordedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"contentSha256":{"type":"string"}},"required":["id","contaminationId","subject","note","recordedBy","recordedAt","contentSha256"]},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyContaminationMitigation"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyGatePassageList":{"type":"object","properties":{"passages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"readingId":{"type":"string"},"bridgeId":{"type":"string"},"bridgeName":{"type":"string"},"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"siteName":{"type":["string","null"]},"direction":{"type":"string","enum":["in","out","unknown"]},"lane":{"type":["string","null"]},"passedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"vehicle":{"type":["object","null"],"properties":{"id":{"type":"string"},"plate":{"type":"string"},"kind":{"type":"string"}},"required":["id","plate","kind"],"additionalProperties":false},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"lotCode":{"type":"string"},"commodity":{"type":"string"}},"required":["id","lotCode","commodity"],"additionalProperties":false}},"unitIds":{"type":"array","items":{"type":"string"}},"unresolvedCount":{"type":"integer","minimum":0},"contentSha256":{"type":"string"}},"required":["id","readingId","bridgeId","bridgeName","siteId","siteName","direction","lane","passedAt","vehicle","lots","unitIds","unresolvedCount","contentSha256"],"additionalProperties":false,"description":"A passage a fixed gate reader saw (CUS-308)"},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyGatePassage"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyGatePassage":{"type":"object","properties":{"id":{"type":"string"},"readingId":{"type":"string"},"bridgeId":{"type":"string"},"bridgeName":{"type":"string"},"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"siteName":{"type":["string","null"]},"direction":{"type":"string","enum":["in","out","unknown"]},"lane":{"type":["string","null"]},"passedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"vehicle":{"type":["object","null"],"properties":{"id":{"type":"string"},"plate":{"type":"string"},"kind":{"type":"string"}},"required":["id","plate","kind"],"additionalProperties":false},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"lotCode":{"type":"string"},"commodity":{"type":"string"}},"required":["id","lotCode","commodity"],"additionalProperties":false}},"unitIds":{"type":"array","items":{"type":"string"}},"unresolvedCount":{"type":"integer","minimum":0},"contentSha256":{"type":"string"}},"required":["id","readingId","bridgeId","bridgeName","siteId","siteName","direction","lane","passedAt","vehicle","lots","unitIds","unresolvedCount","contentSha256"],"additionalProperties":false,"description":"A passage a fixed gate reader saw (CUS-308)"},"CustodyBridgeProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyBridgeEventsResult":{"type":"object","properties":{"results":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"accepted":{"type":"boolean","enum":[true]},"readingId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"duplicate":{"type":"boolean"},"usable":{"type":"boolean"},"passageId":{"type":["string","null"]},"passageOutcome":{"type":"string","enum":["recorded","no_match","vehicles_ambiguous"]}},"required":["accepted","readingId","duplicate","usable"],"additionalProperties":false},{"type":"object","properties":{"accepted":{"type":"boolean","enum":[false]},"reason":{"type":"string","enum":["bad_signature","wrong_key","malformed_envelope","bridge_unknown","bridge_revoked","bridge_expired","bridge_pending_activation","tenant_mismatch","plan_not_entitled","stale","unsupported_device_class","malformed_payload"]}},"required":["accepted","reason"],"additionalProperties":false}],"description":"What became of one event, in the order sent"}}},"required":["results"],"additionalProperties":false},"CustodyBridgeEvents":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"bridgeId":{"type":"string","description":"The bridge’s id (a UUID), issued at registration"},"deviceClass":{"type":"string","description":"One of weighing_scale, barcode_scanner, rfid_uhf_reader, nfc_reader, label_printer, gate_reader. Taken today: weighing_scale (a weight a receipt can take) and gate_reader (a passage at a site’s gate, CUS-308)"},"sourceId":{"type":"string","description":"The device-local id of the event (a weighing session, a ticket). With bridgeId and occurredAt, the deduplication key"},"occurredAt":{"type":"string","description":"When the device read it, ISO 8601 with offset. Refused as `stale` further than 5 minutes from the server’s clock either way"},"payload":{"type":"object","additionalProperties":{},"description":"For a scale: vendor, model, serial, weightKg, stability, tareKg, grossKg, netKg, operatorId, lotId, vesselId, scaleLocalTimestamp. For a gate reader: serial, vendor, model, direction (in | out | unknown), lane, reads (1 to 32) of { kind (qr | barcode | datamatrix | rfid_uhf | rfid_hf | nfc_ntag), value }, everything the reader saw in one passage"},"signature":{"type":"string","description":"HMAC-SHA256, base64"}},"required":["bridgeId","deviceClass","sourceId","occurredAt","payload","signature"],"additionalProperties":{},"description":"A signed event of a hardware bridge"},"minItems":1,"maxItems":100}},"required":["events"],"additionalProperties":false,"description":"POST /v1/custody/bridge/events payload"},"CustodyDeviceKeyList":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u","description":"The key’s id: a lowercase UUID the phone chose when it generated the key"},"label":{"type":"string"},"algorithm":{"type":"string","enum":["ecdsa-p256-sha256"]},"fingerprint":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"sha256 of the public key’s DER bytes"},"hardwareBacked":{"type":["boolean","null"]},"registeredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"mine":{"type":"boolean","description":"The key signs for the caller"},"holder":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["user"]},"name":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["member"]}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"],"additionalProperties":false}],"description":"Whose phone: an active member by name, a member with no name, or someone no longer in the workspace"}},"required":["id","label","algorithm","fingerprint","hardwareBacked","registeredAt","revokedAt","mine","holder"],"additionalProperties":false,"description":"A phone’s signing key"},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyDeviceKey"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyDeviceKey":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u","description":"The key’s id: a lowercase UUID the phone chose when it generated the key"},"label":{"type":"string"},"algorithm":{"type":"string","enum":["ecdsa-p256-sha256"]},"fingerprint":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"sha256 of the public key’s DER bytes"},"hardwareBacked":{"type":["boolean","null"]},"registeredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"mine":{"type":"boolean","description":"The key signs for the caller"},"holder":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["user"]},"name":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["member"]}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"],"additionalProperties":false}],"description":"Whose phone: an active member by name, a member with no name, or someone no longer in the workspace"}},"required":["id","label","algorithm","fingerprint","hardwareBacked","registeredAt","revokedAt","mine","holder"],"additionalProperties":false,"description":"A phone’s signing key"},"CustodyDeviceKeyProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyDeviceKeyRegistered":{"type":"object","properties":{"key":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u","description":"The key’s id: a lowercase UUID the phone chose when it generated the key"},"label":{"type":"string"},"algorithm":{"type":"string","enum":["ecdsa-p256-sha256"]},"fingerprint":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"sha256 of the public key’s DER bytes"},"hardwareBacked":{"type":["boolean","null"]},"registeredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"mine":{"type":"boolean","description":"The key signs for the caller"},"holder":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["user"]},"name":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["member"]}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"],"additionalProperties":false}],"description":"Whose phone: an active member by name, a member with no name, or someone no longer in the workspace"}},"required":["id","label","algorithm","fingerprint","hardwareBacked","registeredAt","revokedAt","mine","holder"],"additionalProperties":false,"description":"A phone’s signing key"},"replayed":{"type":"boolean","description":"The same key was registered before under this id: nothing was written"}},"required":["key","replayed"],"additionalProperties":false},"CustodyDeviceKeyRegistration":{"type":"object","properties":{"id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u","description":"The key’s id: a lowercase UUID the phone chose when it generated the key"},"publicKeySpki":{"type":"string","minLength":60,"maxLength":1024,"description":"The public key: base64 of its DER SubjectPublicKeyInfo, ECDSA on P-256"},"label":{"type":"string","minLength":1,"maxLength":80,"description":"What the phone is, from its model (\"Android · Pixel 7\")"},"hardwareBacked":{"type":["boolean","null"],"description":"Whether the phone reports the key as held in secure hardware. Declared, not attested"}},"required":["id","publicKeySpki","label"],"additionalProperties":false,"description":"Register the caller’s phone key"},"CustodyEventRecorded":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"subjectType":{"type":"string"},"subjectId":{"type":"string"},"occurredAt":{"type":"string"},"recordedAt":{"type":"string"},"contentSha256":{"type":["string","null"],"description":"The fingerprint of the event’s content, as the audit trail recorded it"},"deviceSignature":{"type":["string","null"],"enum":["verified","bad_signature","photos_mismatch","unknown_key","revoked_key",null],"description":"`verified`: signed on the device: the phone’s registered key signed this event and these files. Every other value flags the event, which is kept: `bad_signature` (the event recorded is not what the phone signed, or another key signed it), `photos_mismatch` (the files are not the ones signed), `unknown_key` (no key of this user in this workspace has that id), `revoked_key` (the key was revoked before the event arrived)."},"replayed":{"type":"boolean","description":"The id had already recorded this event: nothing was written"}},"required":["id","eventType","subjectType","subjectId","occurredAt","recordedAt","contentSha256","deviceSignature","replayed"],"additionalProperties":false},"CustodyEventCreation":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{15,63}$/u","description":"The event’s id, chosen by the client: 16 to 64 url-safe characters"},"eventType":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"subjectType":{"type":"string","enum":["plot","batch","shipment","party","site","transport","certificate","document","dds"]},"subjectId":{"type":"string","minLength":1,"maxLength":64},"occurredAt":{"type":"string","format":"date-time","description":"When it happened (bounded like any capture)"},"location":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}},"required":["lat","lng"],"additionalProperties":false},"attachments":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":50,"description":"Ids of this workspace’s documents the event carries"},"payload":{"type":"object","additionalProperties":{},"description":"The typed content for the event type"},"deviceSignature":{"type":"object","properties":{"kind":{"type":"string","enum":["ecdsa-p256-sha256"]},"keyId":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u","description":"The key’s id: a lowercase UUID the phone chose when it generated the key"},"signedAt":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/u","description":"When the phone signed: ISO 8601 in UTC with milliseconds"},"photoSha256s":{"type":"array","items":{"type":"string","pattern":"^[0-9a-f]{64}$/u"},"maxItems":50,"description":"The sha256 (lowercase hex) of the BYTES of every file the event carries, as the phone hashed them"},"signature":{"type":"string","maxLength":200,"pattern":"^[A-Za-z0-9+/]+={0,2}$/u","description":"ECDSA P-256 over SHA-256, DER-encoded, base64, over the UTF-8 of the JCS (RFC 8785) of `{ v: 1, kind: \"origonex.device-event-signature\", contentSha256, keyId, signedAt, photoSha256s }`, where `contentSha256` is the sha256 of the JCS of `{ v: 1, type: \"device_event\", tenantId, eventId, eventType, subjectType, subjectId, occurredAt, location: [lon, lat] as text at 7 decimals or null, payload }` and `photoSha256s` is sorted"}},"required":["kind","keyId","signedAt","photoSha256s","signature"],"additionalProperties":false,"description":"The phone’s signature over the event and its files"},"customFields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."},"description":"Custom values to store with the record, by field key (`null` clears). Needs the `custom-fields.write` scope besides this operation’s own. Judged against the definitions as of `customFieldsAsOf` and the record as stored; a refusal (`custom_field_invalid`, `custom_field_required`, …) rolls the whole request back. Absent: nothing is written and no field is required. Written only when this call creates the record: a replay of the same record writes nothing. Never part of the record’s content hash or proof."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the field definitions your form showed were read (≤ 30 days ago); the values are judged as of that moment. Omit it to be judged now."}},"required":["id","eventType","subjectType","subjectId","occurredAt"],"additionalProperties":false},"CustodyCriticalLinkResult":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"commodity":{"type":"string"},"check":{"type":["string","null"],"description":"The check that ran (`wood.sawmill_yield`…); null for a commodity with no stage template."},"stage":{"type":["string","null"],"description":"The stage the critical link sits at."},"templateVersion":{"type":["string","null"]},"status":{"type":"string","enum":["pass","warn","not_applicable"],"description":"`pass`: the link holds. `warn`: it fails, or cannot be proven; see `findings`. `not_applicable`: the lot has not reached the link, or its commodity has no template."},"basis":{"type":"string","enum":["checked","no_intermediary","single_producer","not_reached","no_template","unstaged"],"description":"`checked`: lots at the link were judged. `no_intermediary`: the chain skips an optional middle hand. `single_producer`: coffee that never stopped being one producer’s. `not_reached`, `no_template`: nothing to judge yet, or ever. `unstaged`: the chain records no stage."},"instances":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"}},"required":["batchId","lotCode"]},"description":"The lots the link was judged at (at most 25)."},"lots":{"type":"integer","minimum":1,"description":"Lots in the upstream chain."},"truncated":{"type":"boolean"},"findings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["unstaged","stage_missing","truncated","origin_untraced","intermediary_without_sources","sawing_not_recorded","yield_above_range","yield_unmeasured","indirect_untraced","hold_exceeded","silo_without_intake","mass_balance","blend_components_unrecorded"],"description":"`unstaged`: no lot of the chain records its stage, so the link cannot be located. `stage_missing`: the lot is past the critical stage, but no lot of its chain was recorded at it. `truncated`: the chain is larger than one check reads. `origin_untraced`: an origin lot with no plot (or one this workspace cannot see) feeds the critical link. `intermediary_without_sources`: a village buyer’s, collector’s or reseller’s lot names no lot it bought. `sawing_not_recorded`: sawn timber with no sawing (or one with unknown quantities) behind it. `yield_above_range`: sawn timber above the sawing’s yield range. `yield_unmeasured`: a sawing whose yield could not be measured. `indirect_untraced`: finished animals with no rearing or calf origin recorded. `hold_exceeded`: fresh fruit bunches milled later after their recorded harvest than bunches keep. `silo_without_intake`: a silo lot that records no intake. `mass_balance`: a mass-balance lot in the chain, whose physical origin cannot be proven. `blend_components_unrecorded`: a lot that lists several producers but records none of their lots."},"batchId":{"type":"string","minLength":1,"description":"The lot the finding is about, often upstream of the lot checked."},"lotCode":{"type":["string","null"],"description":"Its lot code; null for a lot this workspace cannot see."},"params":{"type":"object","additionalProperties":{"type":"string"},"description":"Values for the message: `stage` (the missing stage), `yieldPct` / `maxPct` (the yield and the range’s top, in percent), `hours` / `maxHours` (bunch age at milling and its limit)."}},"required":["code","batchId","lotCode","params"],"description":"One way the critical link fails."},"description":"At most 25."},"findingsTotal":{"type":"integer","minimum":0}},"required":["batchId","lotCode","commodity","check","stage","templateVersion","status","basis","instances","lots","truncated","findings","findingsTotal"],"description":"The critical-link check of a lot's chain of custody."},"CustodyCriticalLinkProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyChainCertificates":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"lots":{"type":"integer","minimum":0,"description":"Lots in the upstream chain read."},"entries":{"type":"array","items":{"type":"object","properties":{"certificateId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"certifier":{"type":"string","description":"The scheme (`fsc`, `rspo`, `custom`…)."},"certifierCustom":{"type":["string","null"]},"certificateNumber":{"type":"string"},"holderType":{"type":"string","enum":["batch","party","plot","site","transformation"],"description":"What the certificate is linked to: a lot, a party, a plot, a site or a stage (`transformation`)."},"holderId":{"type":"string"},"via":{"type":"string","enum":["lot","producer","origin_plot","stage","stage_site","stage_site_owner","receipt_site","receipt_site_owner","receiving_party"],"description":"`lot`: the lot’s own certificate. `producer`: the party that produced a lot no transformation made. `origin_plot`: a plot a harvested lot came from. `stage`: the transformation that made the lot. `stage_site` / `stage_site_owner`: the site that transformation happened at, and the party that owns it. `receipt_site` / `receipt_site_owner` / `receiving_party`: the site that received the lot, its owner, and the party that received it."},"batchId":{"type":"string"},"lotCode":{"type":"string"},"passedAt":{"type":"string","format":"date-time","description":"When the material passed there: the production, the transformation, the receipt."},"stepId":{"type":["string","null"],"description":"The transformation or the receipt that passage is, when it is one."},"status":{"type":"string","enum":["in_force","expired","not_yet_valid","suspended"],"description":"The certificate at that moment: `in_force`, `expired` (it had ended), `not_yet_valid` (it started later) or `suspended` (an open flag says suspended, withdrawn or invalid)."},"validFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$/u"},"validUntil":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$/u","description":"Its last day in force."},"inherited":{"type":"boolean","description":"It reaches the lot asked about through a segregated chain, so the lot carries that certification; false behind a mass-balance lot."}},"required":["certificateId","certifier","certifierCustom","certificateNumber","holderType","holderId","via","batchId","lotCode","passedAt","stepId","status","validFrom","validUntil","inherited"],"description":"One certificate judged at one passage of the chain."},"description":"Every certificate at every passage, from the lot back to the land."},"findingsTotal":{"type":"integer","minimum":0,"description":"Entries not in force (`chain.certificates_valid` reports the first)."}},"required":["batchId","lotCode","lots","entries","findingsTotal"],"description":"The certificates a lot's chain of custody met, where it met them."},"CustodyChainCertificatesProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyLotClaims":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"claims":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"origin":{"type":"string","enum":["declared","computed"],"description":"`declared`: what the supplier’s invoice states; `computed`: the step that made the lot."},"category":{"type":["string","null"],"enum":["fsc_100","fsc_mix_percent","fsc_mix_credit","fsc_controlled_wood","pefc_certified","pefc_controlled_sources","rspo_identity_preserved","rspo_segregated","rspo_mass_balance","ra_identity_preserved","ra_mixed_identity_preserved","ra_segregated","ra_mass_balance","fairtrade_segregated","fairtrade_mass_balance","rtrs_segregated","rtrs_mass_balance","proterra_identity_preserved","proterra_segregated","four_c_segregated","four_c_mass_balance",null]},"percentage":{"type":["integer","null"]},"originRef":{"type":["string","null"]},"declarationId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"certificateCode":{"type":["string","null"]},"certificateId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"supersedesId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"declaredAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"transformationId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"system":{"type":["string","null"],"enum":["transfer","percentage","credit","identity_preserved","segregated","mass_balance","mixed_identity_preserved",null],"description":"The control system: FSC and PEFC `transfer` (PEFC: physical separation), `percentage`, `credit`; RSPO `identity_preserved`, `segregated`, `mass_balance`; Rainforest Alliance `identity_preserved`, `segregated`, `mass_balance` (not for coffee: CUS-602), `mixed_identity_preserved`; Fairtrade and RTRS `segregated`, `mass_balance`; ProTerra `identity_preserved`, `segregated`."},"creditDebit":{"type":["string","null"],"pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"accountId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"contentSha256":{"type":"string"}},"required":["batchId","scheme","origin","category","percentage","originRef","declarationId","certificateCode","certificateId","supersedesId","declaredAt","transformationId","system","creditDebit","accountId","contentSha256"],"additionalProperties":false}},"declarations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"category":{"type":"string","enum":["fsc_100","fsc_mix_percent","fsc_mix_credit","fsc_controlled_wood","pefc_certified","pefc_controlled_sources","rspo_identity_preserved","rspo_segregated","rspo_mass_balance","ra_identity_preserved","ra_mixed_identity_preserved","ra_segregated","ra_mass_balance","fairtrade_segregated","fairtrade_mass_balance","rtrs_segregated","rtrs_mass_balance","proterra_identity_preserved","proterra_segregated","four_c_segregated","four_c_mass_balance"]},"percentage":{"type":["integer","null"]},"originRef":{"type":["string","null"]},"certificateCode":{"type":["string","null"]},"certificateId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"supersedesId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"note":{"type":["string","null"]},"declaredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"source":{"type":"string"},"contentSha256":{"type":"string"}},"required":["id","batchId","scheme","category","percentage","originRef","certificateCode","certificateId","supersedesId","note","declaredAt","source","contentSha256"],"additionalProperties":false},"description":"Every declaration of the lot, oldest first (corrections included)"},"declarable":{"type":"boolean"}},"required":["batchId","claims","declarations","declarable"],"additionalProperties":false},"CustodyClaimProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyClaimDeclare":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"category":{"type":"string","enum":["fsc_100","fsc_mix_percent","fsc_mix_credit","fsc_controlled_wood","pefc_certified","pefc_controlled_sources","rspo_identity_preserved","rspo_segregated","rspo_mass_balance","ra_identity_preserved","ra_mixed_identity_preserved","ra_segregated","ra_mass_balance","fairtrade_segregated","fairtrade_mass_balance","rtrs_segregated","rtrs_mass_balance","proterra_identity_preserved","proterra_segregated","four_c_segregated","four_c_mass_balance"]},"percentage":{"type":["integer","null"],"minimum":1,"maximum":100},"originRef":{"type":["string","null"],"minLength":1,"maxLength":100},"certificateCode":{"type":["string","null"],"minLength":1,"maxLength":100,"description":"The supplier’s certificate code the invoice states (FSC-C123456…)"},"certificateId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The certificate record, when the company keeps it"},"supersedesId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The lot’s current declaration for the scheme, when correcting it"},"note":{"type":["string","null"],"maxLength":1000}},"required":["scheme","category"],"additionalProperties":false,"description":"POST /v1/custody/batches/{id}/claims payload"},"CustodyCreditAccountList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyCreditAccount"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"]},"CustodyCreditAccount":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"productClass":{"type":"string"},"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"siteName":{"type":["string","null"]},"unitType":{"type":"string","enum":["live_weight_kg","carcass_kg","green_bean_kg","parchment_kg","dried_cherry_kg","wet_bean_kg","dry_bean_kg","cubic_meter","rss_grade","mt_palm_oil","mt_soy","mt_soybean_meal","mt_soybean_oil","kg","mt","liter","piece","head","bag","bale","box","bunch"]},"balance":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"credited":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"debited":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"lastEntryAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","scheme","productClass","siteId","siteName","unitType","balance","credited","debited","lastEntryAt","createdAt"],"additionalProperties":false},"CustodyCreditEntryList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyCreditEntry"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyCreditEntry":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"accountId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"direction":{"type":"string","enum":["credit","debit"]},"quantity":{"type":"string","pattern":"^-?\\d+\\.\\d{3}$/u","description":"A decimal at scale 3"},"transformationId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","accountId","direction","quantity","transformationId","batchId","lotCode","createdAt"],"additionalProperties":false},"CustodyTrademarkLicenceList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"code":{"type":"string"},"registeredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","scheme","code","registeredAt","revokedAt"]}}},"required":["data"]},"CustodyTrademarkLicenceProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyTrademarkLicence":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"code":{"type":"string"},"registeredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"revokedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","scheme","code","registeredAt","revokedAt"]},"CustodyTrademarkLicenceRegisterBody":{"type":"object","properties":{"scheme":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"code":{"type":"string","minLength":2,"maxLength":60}},"required":["scheme","code"],"additionalProperties":false},"CustodyConflict":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"conflict":{"type":"string","enum":["lot_overdrawn","transport_received_twice"]},"subjectType":{"type":"string","enum":["batch","transport"]},"subjectId":{"type":"string"},"batchId":{"type":["string","null"]},"lotCode":{"type":["string","null"]},"transportId":{"type":["string","null"]},"receiptId":{"type":["string","null"]},"unitType":{"type":["string","null"]},"pendingBatchIds":{"type":"array","items":{"type":"string"}},"entries":{"type":"array","items":{"type":"object","properties":{"recordType":{"type":"string","enum":["transport","transformation","receipt"]},"recordId":{"type":"string"},"status":{"type":"string","enum":["kept","flagged","refused"],"description":"`kept`: stored before the conflict arose. `flagged`: stored although it overdraws: it happened. `refused`: not stored (it would duplicate a receipt); what it said is kept here."},"recordedBy":{"type":["string","null"],"description":"The member who recorded it (user id)."},"recordedByName":{"type":["string","null"],"description":"The member's name, as the workspace shows its members."},"source":{"type":["string","null"]},"occurredAt":{"type":["string","null"],"format":"date-time","description":"When it happened on the ground, by the recording device's clock."},"recordedAt":{"type":"string","format":"date-time","description":"When the server stored (or refused) it."},"quantity":{"type":["number","null"],"description":"How much of the lot, in the lot's unit."},"receipt":{"type":["object","null"],"properties":{"outcome":{"type":"string"},"ticketNumber":{"type":["string","null"]},"lines":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string"},"received":{"type":"number"},"accepted":{"type":["number","null"]}},"required":["batchId","received","accepted"]}}},"required":["outcome","ticketNumber","lines"],"description":"A refused receipt: what it said (no free text)."}},"required":["recordType","recordId","status","recordedBy","recordedByName","source","occurredAt","recordedAt","quantity","receipt"]}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"resolvedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"resolution":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["balance_restored"]},"at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"recordType":{"type":"string"},"recordId":{"type":"string"}},"required":["kind","at","recordType","recordId"]},{"type":"object","properties":{"kind":{"type":"string","enum":["explained"]},"at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"by":{"type":["string","null"]},"byName":{"type":["string","null"]},"note":{"type":"string"}},"required":["kind","at","by","byName","note"]},{"type":"null"}]}},"required":["id","conflict","subjectType","subjectId","batchId","lotCode","transportId","receiptId","unitType","pendingBatchIds","entries","createdAt","resolvedAt","resolution"]},"CustodyConflictProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyConflictResolve":{"type":"object","properties":{"note":{"type":"string","minLength":1,"maxLength":1000,"description":"Why the item can close: the surplus is real, or which side is wrong and how it is being put right. Kept on the item; the audit trail records its fingerprint."}},"required":["note"],"additionalProperties":false},"CustodyVisibilityView":{"type":"object","properties":{"batchId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"editable":{"type":"boolean"},"tenantStored":{"type":"boolean"},"batchStored":{"type":"boolean"},"effective":{"type":"object","properties":{"origin.country":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.region":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.municipality":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.plotMap":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesExact":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesRounded":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.producerName":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.area":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"chain.stages":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.plate":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.driver":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.carrier":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.route":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.site":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.yield":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.losses":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.location":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.files":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certificates.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.proof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.recordProof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"unit.serial":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certification.claim":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.contributors":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"custom.fields":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}}}},"inherited":{"type":"object","properties":{"origin.country":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.region":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.municipality":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.plotMap":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesExact":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesRounded":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.producerName":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.area":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"chain.stages":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.plate":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.driver":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.carrier":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.route":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.site":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.yield":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.losses":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.location":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.files":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certificates.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.proof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.recordProof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"unit.serial":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certification.claim":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.contributors":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"custom.fields":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}}}},"defaults":{"type":"object","properties":{"origin.country":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.region":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.municipality":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.plotMap":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesExact":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.coordinatesRounded":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.producerName":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.area":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"chain.stages":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.plate":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.driver":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.carrier":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.route":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transport.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"receipt.weights":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.site":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.yield":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"transformation.losses":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.operator":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"event.location":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"documents.files":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certificates.list":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.proof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"integrity.recordProof":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"unit.serial":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"certification.claim":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"origin.contributors":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}},"custom.fields":{"type":"array","items":{"type":"string","enum":["public","buyer","importer"]}}}},"source":{"type":"object","properties":{"origin.country":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.region":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.municipality":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.plotMap":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.coordinatesExact":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.coordinatesRounded":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.producerName":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.area":{"type":"string","enum":["default","legacy","tenant","batch"]},"chain.stages":{"type":"string","enum":["default","legacy","tenant","batch"]},"transport.plate":{"type":"string","enum":["default","legacy","tenant","batch"]},"transport.driver":{"type":"string","enum":["default","legacy","tenant","batch"]},"transport.carrier":{"type":"string","enum":["default","legacy","tenant","batch"]},"transport.route":{"type":"string","enum":["default","legacy","tenant","batch"]},"transport.weights":{"type":"string","enum":["default","legacy","tenant","batch"]},"receipt.operator":{"type":"string","enum":["default","legacy","tenant","batch"]},"receipt.weights":{"type":"string","enum":["default","legacy","tenant","batch"]},"transformation.site":{"type":"string","enum":["default","legacy","tenant","batch"]},"transformation.yield":{"type":"string","enum":["default","legacy","tenant","batch"]},"transformation.losses":{"type":"string","enum":["default","legacy","tenant","batch"]},"event.operator":{"type":"string","enum":["default","legacy","tenant","batch"]},"event.location":{"type":"string","enum":["default","legacy","tenant","batch"]},"documents.list":{"type":"string","enum":["default","legacy","tenant","batch"]},"documents.files":{"type":"string","enum":["default","legacy","tenant","batch"]},"certificates.list":{"type":"string","enum":["default","legacy","tenant","batch"]},"integrity.proof":{"type":"string","enum":["default","legacy","tenant","batch"]},"integrity.recordProof":{"type":"string","enum":["default","legacy","tenant","batch"]},"unit.serial":{"type":"string","enum":["default","legacy","tenant","batch"]},"certification.claim":{"type":"string","enum":["default","legacy","tenant","batch"]},"origin.contributors":{"type":"string","enum":["default","legacy","tenant","batch"]},"custom.fields":{"type":"string","enum":["default","legacy","tenant","batch"]}}},"sensitive":{"type":"array","items":{"type":"string","enum":["origin.country","origin.region","origin.municipality","origin.plotMap","origin.coordinatesExact","origin.coordinatesRounded","origin.producerName","origin.area","chain.stages","transport.plate","transport.driver","transport.carrier","transport.route","transport.weights","receipt.operator","receipt.weights","transformation.site","transformation.yield","transformation.losses","event.operator","event.location","documents.list","documents.files","certificates.list","integrity.proof","integrity.recordProof","unit.serial","certification.claim","origin.contributors","custom.fields"]}},"locked":{"type":"array","items":{"type":"string","enum":["origin.country","origin.region","origin.municipality","origin.plotMap","origin.coordinatesExact","origin.coordinatesRounded","origin.producerName","origin.area","chain.stages","transport.plate","transport.driver","transport.carrier","transport.route","transport.weights","receipt.operator","receipt.weights","transformation.site","transformation.yield","transformation.losses","event.operator","event.location","documents.list","documents.files","certificates.list","integrity.proof","integrity.recordProof","unit.serial","certification.claim","origin.contributors","custom.fields"]}}},"required":["batchId","editable","tenantStored","batchStored","effective","inherited","defaults","source","sensitive","locked"]},"CustodyVisibilityProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyVisibilityPatch":{"type":"object","properties":{"rules":{"type":"object","properties":{"origin.country":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.region":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.municipality":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.plotMap":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.coordinatesExact":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.coordinatesRounded":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.producerName":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.area":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"chain.stages":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transport.plate":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transport.driver":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transport.carrier":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transport.route":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transport.weights":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"receipt.operator":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"receipt.weights":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transformation.site":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transformation.yield":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"transformation.losses":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"event.operator":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"event.location":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"documents.list":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"documents.files":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"certificates.list":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"integrity.proof":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"integrity.recordProof":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"unit.serial":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"certification.claim":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"origin.contributors":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3},"custom.fields":{"type":["array","null"],"items":{"type":"string","enum":["public","buyer","importer"]},"maxItems":3}},"description":"For each field named, the audiences (`public`, `buyer`, `importer`) that may see it, or `null` to inherit. Fields not named keep what they had. `integrity.proof` is visible to every audience and cannot be narrowed: the seal is public by construction, and the whole public proof is withheld with the verifier setting `publicProofEnabled`. A change that only removes audiences is accepted on every plan and with the chain-of-custody programme off; one that adds any needs the programme and the Growth plan."}},"required":["rules"],"additionalProperties":false},"CustodyVisibilityPreview":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"audiences":{"type":"object","properties":{"public":{"type":"object","additionalProperties":{},"description":"The lot’s record (`lot`, `origin`, `stages`, `events`, `transports`, `receipts`, `transformations`, `documents`, `certificates`, `integrity`, `units`) with every key the audience may not see removed."},"buyer":{"type":"object","additionalProperties":{},"description":"The lot’s record (`lot`, `origin`, `stages`, `events`, `transports`, `receipts`, `transformations`, `documents`, `certificates`, `integrity`, `units`) with every key the audience may not see removed."},"importer":{"type":"object","additionalProperties":{},"description":"The lot’s record (`lot`, `origin`, `stages`, `events`, `transports`, `receipts`, `transformations`, `documents`, `certificates`, `integrity`, `units`) with every key the audience may not see removed."},"auditor":{"type":"object","additionalProperties":{},"description":"The lot’s record (`lot`, `origin`, `stages`, `events`, `transports`, `receipts`, `transformations`, `documents`, `certificates`, `integrity`, `units`) with every key the audience may not see removed."},"owner":{"type":"object","additionalProperties":{},"description":"The lot’s record (`lot`, `origin`, `stages`, `events`, `transports`, `receipts`, `transformations`, `documents`, `certificates`, `integrity`, `units`) with every key the audience may not see removed."}}}},"required":["batchId","audiences"]},"CertificateRegistryCheck":{"type":"object","properties":{"certificateId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["valid","suspended","terminated","expired","not_found"],"description":"What the certifier's registry says: valid, suspended, terminated, expired, or not_found (the registry was reached and holds no certificate with this code)."},"checkedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"sourceUrl":{"type":"string","format":"uri"},"verdict":{"type":"object","properties":{"adapterId":{"type":"string"},"certificateCode":{"type":"string"},"registryStatus":{"type":["string","null"]},"statusSince":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"holderName":{"type":["string","null"]},"parentHolderName":{"type":["string","null"]},"holderMatches":{"type":["boolean","null"]},"holderMatchedVia":{"type":["string","null"],"enum":["holder","parent",null]},"holderSource":{"type":["string","null"],"enum":["party","input",null]},"scope":{"type":["object","null"],"additionalProperties":{}},"validFrom":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"mismatches":{"type":"array","items":{"type":"string","enum":["status","holder","valid_until"]}},"verified":{"type":"boolean"}},"required":["adapterId","certificateCode","registryStatus","statusSince","holderName","parentHolderName","holderMatches","holderMatchedVia","holderSource","scope","validFrom","validUntil","mismatches","verified"]},"stored":{"type":"boolean"}},"required":["certificateId","status","checkedAt","sourceUrl","verdict","stored"],"description":"A certificate checked in its certifier's public registry (CUS-206)."},"CertificateRegistryProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CertificateRegistryCheckBody":{"type":"object","properties":{"holderName":{"type":"string","minLength":1,"maxLength":200}},"additionalProperties":false},"CustodyCooperativeList":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The party id, or `workspace` for the workspace itself."},"workspace":{"type":"boolean","description":"True when the cooperative is this workspace."},"name":{"type":"string"},"kind":{"type":["string","null"],"enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other",null],"description":"The party kind; null for the workspace."},"country":{"type":"string"},"sites":{"type":"integer","description":"Sites the cooperative owns (live)."},"activeMembers":{"type":"integer","description":"Members whose membership is open now."}},"required":["id","workspace","name","kind","country","sites","activeMembers"]}}},"required":["items"]},"CustodyCooperativeCandidates":{"type":"object","properties":{"workspace":{"type":"boolean","description":"True when the workspace itself is not listed as a cooperative yet."},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"},"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"country":{"type":"string"}},"required":["id","name","kind","country"]}},"nextCursor":{"type":["string","null"]}},"required":["workspace","items","nextCursor"]},"CustodyCooperativeProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyCooperativeTotals":{"type":"object","properties":{"cooperative":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"workspace":{"type":"boolean"},"name":{"type":"string"},"kind":{"type":["string","null"],"enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other",null],"description":"Party (legal entity) role in the supply chain"},"country":{"type":"string"}},"required":["id","workspace","name","kind","country"]},"period":{"type":"object","properties":{"from":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"to":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"timeZone":{"type":"string"}},"required":["from","to","timeZone"]},"sites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"},"kind":{"type":"string"}},"required":["id","name","kind"]},"description":"The sites the cooperative owns now (live): where open lots are counted."},"members":{"type":"object","properties":{"active":{"type":"integer"},"joined":{"type":"integer"},"left":{"type":"integer"}},"required":["active","joined","left"],"description":"`active`: members at the end of the period. `joined` / `left`: memberships that began / ended inside it."},"plots":{"type":"object","properties":{"count":{"type":"integer"},"areaHa":{"type":"number"}},"required":["count","areaHa"],"description":"Live plots of the members active at the end of the period."},"received":{"type":"object","properties":{"byUnit":{"type":"array","items":{"type":"object","properties":{"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"receipts":{"type":"integer"},"lines":{"type":"integer"},"received":{"type":"number","description":"In the lot's stored unit (kg for a mass)."},"accepted":{"type":"number","description":"In the lot's stored unit (kg for a mass)."}},"required":["unitType","receipts","lines","received","accepted"]}},"byMember":{"type":"array","items":{"type":"object","properties":{"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The member whose lot it was. Null: lots whose producer was not a member when they were received (another producer, or the cooperative itself)."},"name":{"type":["string","null"]},"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"receipts":{"type":"integer"},"received":{"type":"number","description":"In the lot's stored unit (kg for a mass)."},"accepted":{"type":"number","description":"In the lot's stored unit (kg for a mass)."}},"required":["partyId","name","unitType","receipts","received","accepted"]}},"byMemberTruncated":{"type":"boolean"},"byMonth":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","pattern":"^\\d{4}-\\d{2}$/u"},"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"receipts":{"type":"integer"},"received":{"type":"number","description":"In the lot's stored unit (kg for a mass)."},"accepted":{"type":"number","description":"In the lot's stored unit (kg for a mass)."}},"required":["month","unitType","receipts","received","accepted"]}}},"required":["byUnit","byMember","byMemberTruncated","byMonth"],"description":"What the cooperative received in the period: receipt lines whose receiving party (the site owner when the truck was received) is the cooperative, by when it was received on the ground."},"openLots":{"type":"object","properties":{"count":{"type":"integer"},"byUnit":{"type":"array","items":{"type":"object","properties":{"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"lots":{"type":"integer"},"quantity":{"type":"number","description":"In the lot's stored unit (kg for a mass)."}},"required":["unitType","lots","quantity"]}},"items":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":["string","null"]},"commodity":{"type":"string"},"unitType":{"type":"string","enum":["kg","metric_ton","liter","cubic_meter","head","piece","pallet","container","bag","bale","box","bunch"],"description":"Measurement unit for batch quantity: head/piece for cattle/timber individuals; bag/bale/box/bunch for counted sacks, bales, cartons and palm fruit bunches; kg/metric_ton/liter/cubic_meter for measured material. A count is never a mass."},"quantity":{"type":"number","description":"In the lot's stored unit (kg for a mass)."}},"required":["batchId","lotCode","commodity","unitType","quantity"]}}},"required":["count","byUnit","items"],"description":"Lots holding a balance at the cooperative’s sites now (`custody_lot_balance`), whatever the period."},"divergences":{"type":"object","properties":{"receiptDivergence":{"type":"integer"},"custodyConflict":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"alertId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["receipt_divergence","custody_conflict"]},"subjectType":{"type":"string","enum":["batch","transport"]},"subjectId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["alertId","kind","subjectType","subjectId","createdAt"]}}},"required":["receiptDivergence","custodyConflict","items"],"description":"Open `receipt_divergence` and `custody_conflict` items of the compliance queue on a trip to or from the cooperative’s sites, or on a lot that was there, now, whatever the period."}},"required":["cooperative","period","sites","members","plots","received","openLots","divergences"]},"CustodyCooperativeMemberPage":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"membershipId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"},"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"country":{"type":"string"},"joinedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"leftAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plots":{"type":"integer","description":"Live plots the member holds."}},"required":["membershipId","partyId","name","kind","country","joinedAt","leftAt","plots"]},"description":"The shape this list answered before (absent with `shape=v2`)."},"nextCursor":{"type":["string","null"],"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyCooperativeMember"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyCooperativeMember":{"type":"object","properties":{"membershipId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"},"kind":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"country":{"type":"string"},"joinedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"leftAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plots":{"type":"integer","description":"Live plots the member holds."}},"required":["membershipId","partyId","name","kind","country","joinedAt","leftAt","plots"]},"CustodyCooperativeMembership":{"type":"object","properties":{"membershipId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"cooperativeId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"memberPartyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"joinedAt":{"type":"string"},"leftAt":{"type":["string","null"]}},"required":["membershipId","cooperativeId","memberPartyId","joinedAt","leftAt"]},"CustodyCooperativeMemberAdd":{"type":"object","properties":{"memberPartyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"A producer of the workspace (supplier, sub-supplier, processor, smallholder)."},"joinedAt":{"type":"string","format":"date-time","description":"When the producer joined; omitted: now. A calendar day is sent as 00:00 UTC of that day; no later than the day that has begun somewhere on Earth (now + 14 h)."},"leftAt":{"type":"string","format":"date-time","description":"For a membership that has already ended (an imported register): recorded with its whole period, in one transaction. Never before `joinedAt`."}},"required":["memberPartyId"],"additionalProperties":false},"CustodyCooperativeMemberEnd":{"type":"object","properties":{"leftAt":{"type":"string","format":"date-time","description":"When the member left; omitted: now. Never in the future, never before joining."}},"additionalProperties":false},"CustodyLaceySummary":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"file":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":200},"contentType":{"type":"string","enum":["application/pdf","text/csv","application/json"]},"bytesBase64":{"type":"string","description":"The file, base64-encoded."},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"SHA-256 of the file bytes, lowercase hex."}},"required":["filename","contentType","bytesBase64","sha256"],"description":"A generated file, with the hash the audit trail recorded for it."},"lines":{"type":"array","items":{"type":"object","properties":{"scientificName":{"type":["string","null"]},"genus":{"type":["string","null"]},"species":{"type":["string","null"],"description":"`spp.` when only the genus is known."},"commonName":{"type":["string","null"]},"countryOfHarvest":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 of the production plots; null when unknown, or when the chain does not pair this species with a country (see `unpairedCountries`)."},"unpairedCountries":{"type":"array","items":{"type":"string"},"description":"When one origin lot records several species and several countries but not which grew where: that lot’s countries: candidates, NOT a country of harvest. Empty otherwise."},"quantity":{"type":["object","null"],"properties":{"value":{"type":"number"},"unit":{"type":"string","enum":["kg","m3","board_feet","piece","ton_metric","ton_short"]}},"required":["value","unit"],"description":"The quantity to declare on this line; null when the broker declares it."},"originLots":{"type":"array","items":{"type":"string"}},"harvested":{"type":["object","null"],"properties":{"value":{"type":"number"},"unit":{"type":"string"}},"required":["value","unit"],"description":"Harvested at origin, from lots that are exclusively this line."}},"required":["scientificName","genus","species","commonName","countryOfHarvest","unpairedCountries","quantity","originLots","harvested"]}},"gaps":{"type":"array","items":{"type":"string","enum":["species_not_recorded","country_of_harvest_unknown","species_country_pairing_ambiguous","quantity_unit_not_declarable","quantity_split_by_broker","htsus_not_recorded","chain_truncated"]},"description":"What the chain could not answer: fix it on the lot, or the broker supplies it. `quantity_split_by_broker`: more than one line, and no record says how the quantity divides. `species_country_pairing_ambiguous`: an origin lot records several species and several countries but not which grew where."},"generatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["batchId","file","lines","gaps","generatedAt"],"description":"A PPQ 505 declaration summary, prepared for the customs broker."},"CustodyOutputProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyLaceySummaryRequest":{"type":"object","properties":{"format":{"type":"string","enum":["pdf","csv"],"default":"pdf","description":"`pdf` for reading and filing, `csv` for the broker’s spreadsheet."}},"additionalProperties":false},"CustodyBuyerPack":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"pdf":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":200},"contentType":{"type":"string","enum":["application/pdf","text/csv","application/json"]},"bytesBase64":{"type":"string","description":"The file, base64-encoded."},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"SHA-256 of the file bytes, lowercase hex."}},"required":["filename","contentType","bytesBase64","sha256"],"description":"A generated file, with the hash the audit trail recorded for it."},"manifest":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":200},"contentType":{"type":"string","enum":["application/pdf","text/csv","application/json"]},"bytesBase64":{"type":"string","description":"The file, base64-encoded."},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$/u","description":"SHA-256 of the file bytes, lowercase hex."}},"required":["filename","contentType","bytesBase64","sha256"],"description":"A generated file, with the hash the audit trail recorded for it."},"sections":{"type":"object","properties":{"chain":{"type":"boolean"},"origin":{"type":"boolean"},"documents":{"type":"boolean"},"documentFiles":{"type":"boolean"},"certificates":{"type":"boolean"},"seal":{"type":"boolean"}},"required":["chain","origin","documents","documentFiles","certificates","seal"],"description":"Which sections the company’s visibility policy lets a buyer see, so the company knows what the pack carries. The pack itself never says how much was withheld."},"lots":{"type":"integer","minimum":0,"description":"Lots of the chain in the pack."},"truncated":{"type":"boolean"},"generatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["batchId","pdf","manifest","sections","lots","truncated","generatedAt"],"description":"A buyer audit pack: the lot’s chain, documents and certificates as the buyer audience may see them, and a manifest listing the SHA-256 of the PDF and of each shared document."},"CustodyUnitGeneration":{"type":"object","properties":{"status":{"type":"string","enum":["created","replayed"],"description":"`replayed`: this request id had already made these units; nothing new was made."},"requestId":{"type":"string"},"batchId":{"type":"string"},"lotCode":{"type":"string"},"count":{"type":"integer"},"format":{"type":"string","enum":["random","sequential"],"description":"`random`: 12 characters of Crockford base32 from a cryptographic source, after the prefix (at most 8 characters). `sequential`: the prefix and a zero-padded number, going on from the last number used under that prefix on the lot or, with a GTIN, on any lot of that GTIN."},"prefix":{"type":"string"},"gtin":{"type":["string","null"],"description":"GTIN-14, or null."},"firstSerial":{"type":"string"},"lastSerial":{"type":"string"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["status","requestId","batchId","lotCode","count","format","prefix","gtin","firstSerial","lastSerial","createdAt"]},"CustodyUnitProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyUnitGenerateBody":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":10000,"description":"How many units to make, 1 to 10 000."},"format":{"type":"string","enum":["random","sequential"],"default":"random","description":"`random`: 12 characters of Crockford base32 from a cryptographic source, after the prefix (at most 8 characters). `sequential`: the prefix and a zero-padded number, going on from the last number used under that prefix on the lot or, with a GTIN, on any lot of that GTIN."},"prefix":{"type":"string","maxLength":16,"description":"Optional. Letters, digits and hyphens, starting with a letter or digit; stored upper-case. The whole serial fits the 20 characters of GS1 AI (21)."},"digits":{"type":"integer","minimum":1,"maximum":12,"description":"Sequential only (CUS-607): how many digits the numbers are padded to: `D-0152-017` is 3. At least the digits of the run’s last number, at most 12, and the whole serial still fits 20 characters. Omitted: at least 4."},"gtin":{"type":"string","pattern":"^(\\d{8}|\\d{12}|\\d{13}|\\d{14})$/u","description":"Optional: the company's GTIN for this product (GS1 AI 01), check digit included. Stored as GTIN-14. With it, each unit gets a GS1 Digital Link, and a serial is unique across every lot of the GTIN."},"requestId":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,64}$/u","description":"Chosen by the client, once per generation (a UUID is fine). Sending the same request again returns what the first one made instead of making more; the same id with a different request is refused with 409."}},"required":["count","requestId"],"additionalProperties":false},"CustodyUnitPage":{"type":"object","properties":{"batchId":{"type":"string","description":"The shape this list answered before (absent with `shape=v2`)."},"lotCode":{"type":"string","description":"The shape this list answered before (absent with `shape=v2`)."},"total":{"type":"integer","description":"The shape this list answered before (absent with `shape=v2`)."},"nextCursor":{"type":["string","null"],"description":"The shape this list answered before (absent with `shape=v2`)."},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"serial":{"type":"string"},"gtin":{"type":["string","null"]},"status":{"type":"string","enum":["active","voided"]},"statusChangedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"pageUrl":{"type":"string","description":"The unit's public page: what a QR on the piece encodes when the company has no GTIN. The key in it opens the page: treat it like the printed mark."},"digitalLink":{"type":["string","null"],"description":"The unit's GS1 Digital Link (`…/dl/01/{gtin}/10/{lot}/21/{serial}?ox={key}`), when it has a GTIN; it opens the same page."}},"required":["id","serial","gtin","status","statusChangedAt","createdAt","pageUrl","digitalLink"]},"description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyUnit"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyUnit":{"type":"object","properties":{"id":{"type":"string"},"serial":{"type":"string"},"gtin":{"type":["string","null"]},"status":{"type":"string","enum":["active","voided"]},"statusChangedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"pageUrl":{"type":"string","description":"The unit's public page: what a QR on the piece encodes when the company has no GTIN. The key in it opens the page: treat it like the printed mark."},"digitalLink":{"type":["string","null"],"description":"The unit's GS1 Digital Link (`…/dl/01/{gtin}/10/{lot}/21/{serial}?ox={key}`), when it has a GTIN; it opens the same page."}},"required":["id","serial","gtin","status","statusChangedAt","createdAt","pageUrl","digitalLink"]},"CustodyUnitRecordPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyUnitRecord"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"]},"CustodyUnitRecord":{"type":"object","properties":{"id":{"type":"string"},"serial":{"type":"string"},"gtin":{"type":["string","null"]},"status":{"type":"string","enum":["active","voided"]},"statusChangedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"pageUrl":{"type":"string","description":"The unit's public page: what a QR on the piece encodes when the company has no GTIN. The key in it opens the page: treat it like the printed mark."},"digitalLink":{"type":["string","null"],"description":"The unit's GS1 Digital Link (`…/dl/01/{gtin}/10/{lot}/21/{serial}?ox={key}`), when it has a GTIN; it opens the same page."},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","serial","gtin","status","statusChangedAt","createdAt","pageUrl","digitalLink","batchId","lotCode","updatedAt"]},"CustodyAuditorOpinionList":{"type":"object","properties":{"opinions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"engagementId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"auditorName":{"type":["string","null"]},"verdict":{"type":"string","enum":["conforming","conforming_with_observations","nonconforming","inconclusive"],"description":"What the auditor concluded for what was examined: conforming, conforming_with_observations (points to improve that do not change the conclusion), nonconforming, or inconclusive (the auditor could not conclude; not a pass)."},"text":{"type":"string"},"scope":{"type":"array","items":{"type":"string","enum":["origin","transport","receipt","transformation","documents","certificates"],"description":"A part of the lot’s record the opinion covers, named as the lot page’s tabs are."}},"signedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"status":{"type":"string","enum":["current","replaced"]},"supersedesOpinionId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"replacementReason":{"type":["string","null"]},"replacedBy":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"signedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","signedAt"],"additionalProperties":false},"contentSha256":{"type":"string","pattern":"^[0-9a-f]{64}$/u"},"signature":{"type":"object","properties":{"alg":{"type":"string"},"sig":{"type":"string"},"pubkey":{"type":"string"}},"required":["alg","sig","pubkey"],"additionalProperties":false},"integrity":{"type":"object","properties":{"hashMatches":{"type":"boolean","description":"The fingerprint recomputed from the opinion as stored now equals its own."},"ledgerMatches":{"type":"boolean","description":"The audit trail’s record of the signing attests this same fingerprint."},"signatureValid":{"type":"boolean","description":"The detached signature verifies over the fingerprint with its public key."},"intact":{"type":"boolean","description":"All three hold."}},"required":["hashMatches","ledgerMatches","signatureValid","intact"],"additionalProperties":false}},"required":["id","batchId","engagementId","auditorName","verdict","text","scope","signedAt","status","supersedesOpinionId","replacementReason","replacedBy","contentSha256","signature","integrity"],"additionalProperties":false},"description":"The shape this list answered before (absent with `shape=v2`)."},"truncated":{"type":"boolean","description":"The shape this list answered before (absent with `shape=v2`)."},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyAuditorOpinion"},"description":"With `shape=v2`: the page, in place of the older keys."},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["pageInfo"]},"CustodyAuditorOpinion":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"engagementId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"auditorName":{"type":["string","null"]},"verdict":{"type":"string","enum":["conforming","conforming_with_observations","nonconforming","inconclusive"],"description":"What the auditor concluded for what was examined: conforming, conforming_with_observations (points to improve that do not change the conclusion), nonconforming, or inconclusive (the auditor could not conclude; not a pass)."},"text":{"type":"string"},"scope":{"type":"array","items":{"type":"string","enum":["origin","transport","receipt","transformation","documents","certificates"],"description":"A part of the lot’s record the opinion covers, named as the lot page’s tabs are."}},"signedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"status":{"type":"string","enum":["current","replaced"]},"supersedesOpinionId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"replacementReason":{"type":["string","null"]},"replacedBy":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"signedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","signedAt"],"additionalProperties":false},"contentSha256":{"type":"string","pattern":"^[0-9a-f]{64}$/u"},"signature":{"type":"object","properties":{"alg":{"type":"string"},"sig":{"type":"string"},"pubkey":{"type":"string"}},"required":["alg","sig","pubkey"],"additionalProperties":false},"integrity":{"type":"object","properties":{"hashMatches":{"type":"boolean","description":"The fingerprint recomputed from the opinion as stored now equals its own."},"ledgerMatches":{"type":"boolean","description":"The audit trail’s record of the signing attests this same fingerprint."},"signatureValid":{"type":"boolean","description":"The detached signature verifies over the fingerprint with its public key."},"intact":{"type":"boolean","description":"All three hold."}},"required":["hashMatches","ledgerMatches","signatureValid","intact"],"additionalProperties":false}},"required":["id","batchId","engagementId","auditorName","verdict","text","scope","signedAt","status","supersedesOpinionId","replacementReason","replacedBy","contentSha256","signature","integrity"],"additionalProperties":false},"CustodyAuditorOpinionProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyGovDocumentSupport":{"type":"object","properties":{"fetch":{"type":"object","properties":{"enabled":{"type":"boolean"},"kinds":{"type":"array","items":{"type":"string"}}},"required":["enabled","kinds"]}},"required":["fetch"]},"CustodyGovDocumentProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustodyGovDocumentImportResult":{"type":"object","properties":{"replayed":{"type":"boolean"},"contentChanged":{"type":"boolean"},"document":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"source":{"type":"string","enum":["upload","registry"]},"sourceSha256":{"type":"string"},"status":{"type":"string","enum":["pending","applied"]},"outcome":{"type":["string","null"],"enum":["created","matched",null]},"transportId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transport":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"plate":{"type":["string","null"]}},"required":["id","status","plate"]},"document":{"type":"object","properties":{"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"controlCode":{"type":["string","null"]},"issuingAgency":{"type":["string","null"]},"purpose":{"type":["string","null"]},"sourceDocumentNumber":{"type":["string","null"]},"origin":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"destination":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"transportMode":{"type":["string","null"],"enum":["road","rail","river","on_foot","other",null]},"plates":{"type":"array","items":{"type":"string"}},"itinerary":{"type":"array","items":{"type":"object","properties":{"municipality":{"type":"string"},"state":{"type":["string","null"]}},"required":["municipality","state"]}},"items":{"type":"array","items":{"type":"object","properties":{"species":{"type":"string"},"commonName":{"type":["string","null"]},"product":{"type":["string","null"]},"unit":{"type":"string","enum":["cubic_meter","head"]},"quantity":{"type":"number"}},"required":["species","commonName","product","unit","quantity"]}},"animalIds":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string","enum":["sisbov"]},"id":{"type":"string"}},"required":["scheme","id"]}},"animalIdWarnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["malformed","repeated","more_than_head"]},"value":{"type":["string","null"]}},"required":["code","value"]}}},"required":["kind","number","series","issuingState","issuedAt","validUntil","controlCode","issuingAgency","purpose","sourceDocumentNumber","origin","destination","transportMode","plates","itinerary","items","animalIds","animalIdWarnings"],"description":"The document as read: the fields every DOF, GF and GTA prints"},"proposal":{"type":"object","properties":{"vehicle":{"type":["object","null"],"properties":{"vehicleId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plate":{"type":"string"}},"required":["vehicleId","plate"]},"plate":{"type":["string","null"]},"origin":{"type":["object","null"],"properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"}},"required":["siteId","partyId","name"]},"destination":{"type":["object","null"],"properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"}},"required":["siteId","partyId","name"]},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"batchId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"candidates":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"available":{"type":"number"}},"required":["batchId","lotCode","available"]}}},"required":["index","batchId","candidates"]}}},"required":["vehicle","plate","origin","destination","items"]},"differences":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"field":{"type":"string","enum":["plate","origin","destination","species","quantity","unit","validity"]},"species":{"type":["string","null"]},"document":{"type":["string","null"]},"transport":{"type":["string","null"]},"fixable":{"type":"boolean"}},"required":["key","field","species","document","transport","fixable"],"description":"One field where the document and the transport disagree"}},"resolutions":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"field":{"type":"string"},"action":{"type":"string","enum":["accept","fix"]},"document":{"type":["string","null"]},"transport":{"type":["string","null"]}},"required":["key","field","action","document","transport"]}},"candidates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"plate":{"type":["string","null"]},"originName":{"type":["string","null"]},"destinationName":{"type":["string","null"]},"when":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","plate","originName","destinationName","when"]}},"importedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"appliedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","kind","number","series","issuingState","issuedAt","validUntil","source","sourceSha256","status","outcome","transportId","transport","document","proposal","differences","resolutions","candidates","importedAt","appliedAt","updatedAt"],"description":"An imported government transport document and its check"}},"required":["replayed","contentChanged","document"]},"CustodyGovDocumentImport":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":524288},"contentBase64":{"type":"string","minLength":4,"maxLength":699052,"pattern":"^[A-Za-z0-9+/]+={0,2}$/u"},"lookup":{"type":"object","properties":{"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9./-]{0,59}$/u"},"issuingState":{"type":"string","pattern":"^[A-Za-z]{2}$/u"},"series":{"type":"string","pattern":"^[A-Za-z0-9./-]{1,20}$/u"}},"required":["kind","number","issuingState"],"additionalProperties":false}},"additionalProperties":false,"description":"A government transport document to import"},"CustodyGovDocumentList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustodyGovDocumentSummary"}},"pageInfo":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["nextCursor","hasMore"]}},"required":["data","pageInfo"]},"CustodyGovDocumentSummary":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"source":{"type":"string","enum":["upload","registry"]},"sourceSha256":{"type":"string"},"status":{"type":"string","enum":["pending","applied"]},"outcome":{"type":["string","null"],"enum":["created","matched",null]},"transportId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"document":{"type":"object","properties":{"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"controlCode":{"type":["string","null"]},"issuingAgency":{"type":["string","null"]},"purpose":{"type":["string","null"]},"sourceDocumentNumber":{"type":["string","null"]},"origin":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"destination":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"transportMode":{"type":["string","null"],"enum":["road","rail","river","on_foot","other",null]},"plates":{"type":"array","items":{"type":"string"}},"itinerary":{"type":"array","items":{"type":"object","properties":{"municipality":{"type":"string"},"state":{"type":["string","null"]}},"required":["municipality","state"]}},"items":{"type":"array","items":{"type":"object","properties":{"species":{"type":"string"},"commonName":{"type":["string","null"]},"product":{"type":["string","null"]},"unit":{"type":"string","enum":["cubic_meter","head"]},"quantity":{"type":"number"}},"required":["species","commonName","product","unit","quantity"]}},"animalIds":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string","enum":["sisbov"]},"id":{"type":"string"}},"required":["scheme","id"]}},"animalIdWarnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["malformed","repeated","more_than_head"]},"value":{"type":["string","null"]}},"required":["code","value"]}}},"required":["kind","number","series","issuingState","issuedAt","validUntil","controlCode","issuingAgency","purpose","sourceDocumentNumber","origin","destination","transportMode","plates","itinerary","items","animalIds","animalIdWarnings"],"description":"The document as read: the fields every DOF, GF and GTA prints"},"resolutions":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"field":{"type":"string"},"action":{"type":"string","enum":["accept","fix"]},"document":{"type":["string","null"]},"transport":{"type":["string","null"]}},"required":["key","field","action","document","transport"]}},"importedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"appliedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","kind","number","series","issuingState","issuedAt","validUntil","source","sourceSha256","status","outcome","transportId","document","resolutions","importedAt","appliedAt","updatedAt"],"description":"An imported government transport document, without its check"},"CustodyGovDocument":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"source":{"type":"string","enum":["upload","registry"]},"sourceSha256":{"type":"string"},"status":{"type":"string","enum":["pending","applied"]},"outcome":{"type":["string","null"],"enum":["created","matched",null]},"transportId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transport":{"type":["object","null"],"properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"plate":{"type":["string","null"]}},"required":["id","status","plate"]},"document":{"type":"object","properties":{"kind":{"type":"string","enum":["dof","gf","gta"],"description":"dof: Documento de Origem Florestal (Sinaflor); gf: Guia Florestal (SISFLORA, Pará and Mato Grosso); gta: Guia de Trânsito Animal (GTA-e)."},"number":{"type":"string"},"series":{"type":["string","null"]},"issuingState":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"validUntil":{"type":["string","null"],"format":"date","description":"ISO 8601 calendar date"},"controlCode":{"type":["string","null"]},"issuingAgency":{"type":["string","null"]},"purpose":{"type":["string","null"]},"sourceDocumentNumber":{"type":["string","null"]},"origin":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"destination":{"type":"object","properties":{"holderName":{"type":["string","null"]},"holderTaxId":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["cnpj","cpf"]},"digits":{"type":"string"},"masked":{"type":"string"}},"required":["kind","masked"]},"placeName":{"type":["string","null"]},"placeCode":{"type":["string","null"]},"municipality":{"type":["string","null"]},"municipalityCode":{"type":["string","null"]},"state":{"type":["string","null"]},"point":{"type":["array","null"],"prefixItems":[{"type":"number"},{"type":"number"}]}},"required":["holderName","holderTaxId","placeName","placeCode","municipality","municipalityCode","state","point"]},"transportMode":{"type":["string","null"],"enum":["road","rail","river","on_foot","other",null]},"plates":{"type":"array","items":{"type":"string"}},"itinerary":{"type":"array","items":{"type":"object","properties":{"municipality":{"type":"string"},"state":{"type":["string","null"]}},"required":["municipality","state"]}},"items":{"type":"array","items":{"type":"object","properties":{"species":{"type":"string"},"commonName":{"type":["string","null"]},"product":{"type":["string","null"]},"unit":{"type":"string","enum":["cubic_meter","head"]},"quantity":{"type":"number"}},"required":["species","commonName","product","unit","quantity"]}},"animalIds":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string","enum":["sisbov"]},"id":{"type":"string"}},"required":["scheme","id"]}},"animalIdWarnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["malformed","repeated","more_than_head"]},"value":{"type":["string","null"]}},"required":["code","value"]}}},"required":["kind","number","series","issuingState","issuedAt","validUntil","controlCode","issuingAgency","purpose","sourceDocumentNumber","origin","destination","transportMode","plates","itinerary","items","animalIds","animalIdWarnings"],"description":"The document as read: the fields every DOF, GF and GTA prints"},"proposal":{"type":"object","properties":{"vehicle":{"type":["object","null"],"properties":{"vehicleId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plate":{"type":"string"}},"required":["vehicleId","plate"]},"plate":{"type":["string","null"]},"origin":{"type":["object","null"],"properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"}},"required":["siteId","partyId","name"]},"destination":{"type":["object","null"],"properties":{"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"name":{"type":"string"}},"required":["siteId","partyId","name"]},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"batchId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"candidates":{"type":"array","items":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"available":{"type":"number"}},"required":["batchId","lotCode","available"]}}},"required":["index","batchId","candidates"]}}},"required":["vehicle","plate","origin","destination","items"]},"differences":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"field":{"type":"string","enum":["plate","origin","destination","species","quantity","unit","validity"]},"species":{"type":["string","null"]},"document":{"type":["string","null"]},"transport":{"type":["string","null"]},"fixable":{"type":"boolean"}},"required":["key","field","species","document","transport","fixable"],"description":"One field where the document and the transport disagree"}},"resolutions":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"field":{"type":"string"},"action":{"type":"string","enum":["accept","fix"]},"document":{"type":["string","null"]},"transport":{"type":["string","null"]}},"required":["key","field","action","document","transport"]}},"candidates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"plate":{"type":["string","null"]},"originName":{"type":["string","null"]},"destinationName":{"type":["string","null"]},"when":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","plate","originName","destinationName","when"]}},"importedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"appliedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","kind","number","series","issuingState","issuedAt","validUntil","source","sourceSha256","status","outcome","transportId","transport","document","proposal","differences","resolutions","candidates","importedAt","appliedAt","updatedAt"],"description":"An imported government transport document and its check"},"CustodyGovDocumentMatch":{"type":"object","properties":{"transportId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["transportId"],"additionalProperties":false},"CustodyGovDocumentConfirmResult":{"type":"object","properties":{"replayed":{"type":"boolean"},"document":{"$ref":"#/components/schemas/CustodyGovDocument"}},"required":["replayed","document"]},"CustodyGovDocumentConfirm":{"type":"object","properties":{"vehicleId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"registerVehicle":{"type":"boolean"},"origin":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"destination":{"type":"object","properties":{"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"partyId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"additionalProperties":false,"description":"A place: one of the workspace’s sites, or one of its parties"},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":99},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["index","batchId"],"additionalProperties":false},"maxItems":100},"resolutions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":260},"action":{"type":"string","enum":["accept","fix"]}},"required":["key","action"],"additionalProperties":false},"maxItems":220}},"additionalProperties":false,"description":"Create the transport, or decide every difference"},"CustodyImportJob":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["validating","invalid","ready","committing","committed","failed","expired"],"description":"`validating` / `committing`: poll again. `ready`: a clean preview, waiting to be committed. `committed`: every row is in. `invalid`: see `errors`; NOTHING was written. `failed`: the job was lost; nothing was written. `expired`: a preview not committed within 24 h."},"replayed":{"type":"boolean","description":"This exact upload was already committed: this is that job, and nothing was written again."},"entities":{"type":"array","items":{"type":"string","enum":["parties","plots","sites","vehicles","drivers","lots","transports","receipts","transformations","units"],"description":"What the file holds. Rows are written in this order, so a lot can name its producer and plots, and a transport its site, vehicle and driver, of the same upload by `#key`."}},"rowCount":{"type":"integer"},"errorCount":{"type":"integer"},"errorsTruncated":{"type":"boolean","description":"More errors were found than `errors` lists (at most 1 000); `errorCount` counts them all."},"errors":{"type":"array","items":{"type":"object","properties":{"file":{"type":"integer","description":"Index of the file in the upload"},"filename":{"type":["string","null"]},"entity":{"type":["string","null"],"enum":["parties","plots","sites","vehicles","drivers","lots","transports","receipts","transformations","units",null],"description":"What the file holds. Rows are written in this order, so a lot can name its producer and plots, and a transport its site, vehicle and driver, of the same upload by `#key`."},"line":{"type":"integer","description":"CSV: the line the row starts on (the header is 1). JSON: the record’s position. 0: the whole file."},"column":{"type":"string","description":"The column (or dotted field); empty for the whole row"},"code":{"type":"string"},"detail":{"type":["string","null"],"description":"The named code a refused write gave (`VEHICLE_PLATE_TAKEN`), never a cell’s value"},"message":{"type":"string","description":"The error in the asked language"}},"required":["file","filename","entity","line","column","code","detail","message"]},"description":"At most 1 000; `errorCount` counts all"},"summary":{"type":"object","additionalProperties":{"type":"object","properties":{"rows":{"type":"integer"},"created":{"type":"integer"},"replayed":{"type":"integer"}},"required":["rows","created","replayed"]}},"rows":{"type":["array","null"],"items":{"type":"object","properties":{"entity":{"type":"string","enum":["parties","plots","sites","vehicles","drivers","lots","transports","receipts","transformations","units"],"description":"What the file holds. Rows are written in this order, so a lot can name its producer and plots, and a transport its site, vehicle and driver, of the same upload by `#key`."},"file":{"type":"integer"},"line":{"type":"integer"},"key":{"type":["string","null"]},"id":{"type":"string"},"replayed":{"type":"boolean"}},"required":["entity","file","line","key","id","replayed"]},"description":"Once committed: the id each row became"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"committedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"expiresAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","replayed","entities","rowCount","errorCount","errorsTruncated","errors","summary","rows","createdAt","updatedAt","committedAt","expiresAt"],"description":"A bulk import job"},"CustodyImportProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]},"CustodyImportCreate":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"entity":{"type":"string","enum":["parties","plots","sites","vehicles","drivers","lots","transports","receipts","transformations","units"],"description":"What the file holds. Rows are written in this order, so a lot can name its producer and plots, and a transport its site, vehicle and driver, of the same upload by `#key`."},"format":{"type":"string","enum":["csv","json"]},"filename":{"type":"string","maxLength":200},"content":{"type":"string","minLength":1,"description":"The file as text (UTF-8). CSV: a header of field names, nested fields dotted (`origin.siteId`), array items indexed (`loads.0.batchId`), lists split on `|`, geometry as WKT or GeoJSON; `,` or `;` separated. JSON: an array of objects in the shape of the entity’s create body. Every row may carry `key`; `#key` in an id field names that row."}},"required":["entity","format","content"],"additionalProperties":false},"minItems":1,"maxItems":12,"description":"Up to 12 files, 4 MB and 5 000 rows together."},"mode":{"type":"string","enum":["preview","commit"],"default":"commit","description":"`commit` (default): check and write, all or nothing. `preview`: check only; the job ends `ready` (confirm it with `POST …/{id}/commit` within 24 h) or `invalid`."},"locale":{"type":"string","minLength":2,"maxLength":16,"description":"The language of the report messages. Omitted: `Accept-Language`, then English."}},"required":["files"],"additionalProperties":false,"description":"POST /v1/custody/imports payload"},"CustomFieldList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomField"}}},"required":["data"],"additionalProperties":false},"CustomField":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme."},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$","description":"The API name. Fixed after creation."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"version":{"type":"integer","minimum":1},"status":{"type":"string","enum":["active","retired"]},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}},"description":"Label per locale (`en`, `pt-BR`, `es`, `fr`, `de`, `it`, `ja`), at least one, ≤ 80 characters. A reader gets the exact locale, then the same language, then the workspace default, then `en`, then the first present. Never machine-translated."},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}},"description":"Help text per locale, ≤ 280 characters."},"required":{"type":"boolean"},"config":{"type":"object","additionalProperties":{},"description":"Per type. `number`: unit, decimals, min, max · `money`: currency, allowedCurrencies, decimals, min, max · `text`: maxLength, multiline, pattern · `date`: notInFuture · `single_choice`: options · `multi_choice`: options, maxSelected · `boolean`: none. Bounds are decimal strings."},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"additionalProperties":false,"description":"Where the field applies; keys depend on the record kind (`batch`: commodities, stages · `event`: eventTypes, commodities · `transport`: commodities, vehicleKinds · `receipt`: commodities, siteKinds · `transformation`: transformationKinds, commodities, outputStages · `site`: siteKinds · `plot`: commodities (applies if any of the plot’s commodities matches) · `party`: partyKinds · `certificate`: none · `vehicle`: vehicleKinds · `driver`: none). An absent key or an empty list means all."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."}},"fieldRoleAccess":{"type":"string","enum":["none","fill"],"description":"Whether a field role (a collector or field agent) is shown the field and may fill it. Defaults to `none` for money, `fill` otherwise."},"sortOrder":{"type":"integer"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"versions":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldVersion"}}},"required":["id","recordKind","key","type","version","status","labels","help","required","config","scope","audiences","fieldRoleAccess","sortOrder","createdAt","updatedAt"],"additionalProperties":false},"CustomFieldVersion":{"type":"object","properties":{"version":{"type":"integer","minimum":1},"status":{"type":"string","enum":["active","retired"]},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}},"description":"Label per locale (`en`, `pt-BR`, `es`, `fr`, `de`, `it`, `ja`), at least one, ≤ 80 characters. A reader gets the exact locale, then the same language, then the workspace default, then `en`, then the first present. Never machine-translated."},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}},"description":"Help text per locale, ≤ 280 characters."},"required":{"type":"boolean"},"config":{"type":"object","additionalProperties":{},"description":"Per type. `number`: unit, decimals, min, max · `money`: currency, allowedCurrencies, decimals, min, max · `text`: maxLength, multiline, pattern · `date`: notInFuture · `single_choice`: options · `multi_choice`: options, maxSelected · `boolean`: none. Bounds are decimal strings."},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"additionalProperties":false,"description":"Where the field applies; keys depend on the record kind (`batch`: commodities, stages · `event`: eventTypes, commodities · `transport`: commodities, vehicleKinds · `receipt`: commodities, siteKinds · `transformation`: transformationKinds, commodities, outputStages · `site`: siteKinds · `plot`: commodities (applies if any of the plot’s commodities matches) · `party`: partyKinds · `certificate`: none · `vehicle`: vehicleKinds · `driver`: none). An absent key or an empty list means all."},"changeNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["version","status","labels","help","required","config","scope","changeNote","createdAt"],"additionalProperties":false,"description":"One version of a field’s definition. Every change (labels, help, requiredness, config, scope, retire, restore) is a new version; each value records the version it was captured under."},"CustomFieldProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustomFieldCreateBody":{"oneOf":[{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["number"]},"config":{"type":"object","properties":{"unit":{"type":"string","minLength":1,"maxLength":12},"decimals":{"type":"integer","minimum":0,"maximum":6,"default":0},"min":{"type":"string"},"max":{"type":"string"}},"default":{"decimals":0},"additionalProperties":false}},"required":["recordKind","key","labels","type"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["money"]},"config":{"type":"object","properties":{"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"allowedCurrencies":{"type":"array","items":{"type":"string","pattern":"^[A-Z]{3}$"},"minItems":1,"maxItems":5},"decimals":{"type":"integer","minimum":0,"maximum":4,"default":2},"min":{"type":"string","default":"0"},"max":{"type":"string"}},"required":["currency"],"additionalProperties":false}},"required":["recordKind","key","labels","type","config"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["text"]},"config":{"type":"object","properties":{"maxLength":{"type":"integer","minimum":1,"maximum":2000,"default":200},"multiline":{"type":"boolean","default":false},"pattern":{"type":"string","enum":["alnum","digits","upper_alnum_dash"]}},"default":{"maxLength":200,"multiline":false},"additionalProperties":false}},"required":["recordKind","key","labels","type"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["date"]},"config":{"type":"object","properties":{"notInFuture":{"type":"boolean"}},"default":{},"additionalProperties":false}},"required":["recordKind","key","labels","type"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["single_choice"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9_]{1,40}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"retired":{"type":"boolean"}},"required":["key","labels"],"additionalProperties":false},"minItems":1,"maxItems":100}},"required":["options"],"additionalProperties":false}},"required":["recordKind","key","labels","type","config"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["multi_choice"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9_]{1,40}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"retired":{"type":"boolean"}},"required":["key","labels"],"additionalProperties":false},"minItems":1,"maxItems":100},"maxSelected":{"type":"integer","minimum":1,"maximum":100}},"required":["options"],"additionalProperties":false}},"required":["recordKind","key","labels","type","config"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean","default":false},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"default":{},"additionalProperties":false},"fieldRoleAccess":{"type":"string","enum":["none","fill"]},"type":{"type":"string","enum":["boolean"]},"config":{"type":"object","properties":{},"default":{},"additionalProperties":false}},"required":["recordKind","key","labels","type"],"additionalProperties":false}],"description":"Create a field (its version 1). It is born visible to the company only (there is no `audiences` key); open it with `PUT /v1/custom-fields/{id}/visibility`."},"CustomFieldPatchBody":{"type":"object","properties":{"labels":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"help":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"es":{"type":"string"},"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"ja":{"type":"string"}}},"required":{"type":"boolean"},"config":{"type":"object","additionalProperties":{}},"scope":{"type":"object","properties":{"commodities":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"stages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"eventTypes":{"type":"array","items":{"type":"string","enum":["harvest","transport","weighing","loading","processing","transformation","shipment","receiving","audit","inspection","mass_balance_credit","mass_balance_claim","geometry_repaired","manual_override","quality_grading","storage_count","treatment","sample_collection","animal_handling"]},"maxItems":100},"vehicleKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"siteKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"transformationKinds":{"type":"array","items":{"type":"string","enum":["split","merge","process","pack","slaughter"]},"maxItems":100},"outputStages":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100},"partyKinds":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"maxItems":100}},"additionalProperties":false},"changeNote":{"type":"string","minLength":1,"maxLength":280}},"additionalProperties":false,"description":"A new version: any of labels, help, required, config, scope, with an optional reason. `type`, `key` and `recordKind` cannot change. A choice option is never deleted; retire it (`retired: true`)."},"CustomFieldStatusChangeBody":{"type":"object","properties":{"changeNote":{"type":"string","minLength":1,"maxLength":280}},"additionalProperties":false,"description":"Retire or restore a field (a new version). Restoring counts against the plan limit."},"CustomFieldVisibilityBody":{"type":"object","properties":{"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"]},"maxItems":4,"description":"The audiences that see the field besides the company; `[]` closes it. Adding any needs the Growth plan; removing is allowed on every plan. `public` on a money or text field is refused (422)."},"fieldRoleAccess":{"type":"string","enum":["none","fill"]}},"required":["audiences"],"additionalProperties":false,"description":"Who sees the field, and whether field roles fill it."},"CustomFieldOrderBody":{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"]},"fieldIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"minItems":1,"maxItems":200}},"required":["recordKind","fieldIds"],"additionalProperties":false,"description":"The record kind’s fields in their new order."},"CustomFieldValuesList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldRecordValues"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"],"additionalProperties":false},"CustomFieldRecordValues":{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme."},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"values":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}}},"required":["recordKind","recordId","values"],"additionalProperties":false},"CustomFieldValueProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"pointer":{"type":"string"},"message":{"type":"string"}},"required":["pointer","message"]}}},"required":["type","title","status","code"]},"CustomFieldValuesWriteResult":{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme."},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"values":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}},"requestId":{"type":"string","description":"The request id the write is stored under."},"replayed":{"type":"boolean","description":"The request id was already written: nothing new was stored."},"changed":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"description":"The keys this write stored a new value for (cleared ones included)."}},"required":["recordKind","recordId","values","requestId","replayed","changed"],"additionalProperties":false},"CustomFieldValuesPatch":{"type":"object","properties":{"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}],"description":"Shape by the field type: `number` a decimal string (a JSON number is accepted and answered as a string) · `money` `{ amount, currency }` · `text` a string · `date` `YYYY-MM-DD` · `single_choice` an option key · `multi_choice` option keys · `boolean` true/false. `null` clears."}},"basedOn":{"type":"object","additionalProperties":{"type":["string","null"],"minLength":1,"maxLength":64},"description":"Per key, the `valueId` you last saw (`null`: none). A mismatch is not refused: the write is kept and the field is flagged as changed on two devices."},"customFieldsAsOf":{"type":"string","format":"date-time","description":"When the definitions your form showed were read; the write is judged as of that moment (≤ 30 days ago). Omit it to be judged now."},"capturedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["values"],"additionalProperties":false,"description":"Set or clear values on one record. `Idempotency-Key` is the request id: a replay answers the stored result. Required fields cannot be cleared."},"CustomFieldValueHistory":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"fieldVersion":{"type":"integer","minimum":1},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"cleared":{"type":"boolean"},"recordedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"capturedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"source":{"type":"string","enum":["web","mobile","api","import","carry","system"]},"recordedBy":{"type":["string","null"]},"apiKeyId":{"type":["string","null"]},"basedOnValueId":{"type":["string","null"]},"erased":{"type":"boolean","description":"The value was erased at the data subject’s request."}},"required":["valueId","key","fieldVersion","value","cleared","recordedAt","capturedAt","source","recordedBy","apiKeyId","basedOnValueId","erased"],"additionalProperties":false}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}},"required":["data","pageInfo"],"additionalProperties":false},"CustomFieldUpstream":{"type":"object","properties":{"root":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"truncated":{"type":"boolean","description":"The walk hit `maxDepth` or the 2 000-node cap: some is missing."},"nodes":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch"]},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"commodity":{"type":"string"},"stage":{"type":["string","null"]},"depth":{"type":"integer","minimum":0},"quantity":{"type":"object","properties":{"value":{"type":"string"},"unit":{"type":"string"}},"required":["value","unit"],"additionalProperties":false},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}}},"required":["recordKind","recordId","lotCode","commodity","stage","depth","quantity","customFields"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["transport"]},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"reference":{"type":["string","null"],"description":"CUS-607: the company’s readable number for the trip, or null."},"plate":{"type":["string","null"],"description":"The plate when the transport recorded it."},"onFoot":{"type":"boolean","description":"CUS-603: a herd driven on foot."},"occurredAt":{"type":"string","format":"date-time","description":"When it left; else when it was loaded, planned or recorded."},"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}}},"required":["recordKind","recordId","reference","plate","onFoot","occurredAt","batchIds","customFields"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["receipt"]},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transport":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"reference":{"type":["string","null"]},"plate":{"type":["string","null"]},"onFoot":{"type":"boolean"}},"required":["id","reference","plate","onFoot"],"additionalProperties":false,"description":"The trip it received, by what names it."},"ticketNumber":{"type":["string","null"]},"receivedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}}},"required":["recordKind","recordId","transport","ticketNumber","receivedAt","batchIds","customFields"],"additionalProperties":false},{"type":"object","properties":{"recordKind":{"type":"string","enum":["transformation"]},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string"},"reference":{"type":["string","null"],"description":"CUS-607: the company’s readable number for the step, or null."},"stepKey":{"type":"string","description":"The template transition (`sawing`, `drying`…), else the kind."},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"inputs":{"type":"array","items":{"type":"object","properties":{"quantity":{"type":"string"},"unit":{"type":"string"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["quantity","unit","batchId"],"additionalProperties":false}},"outputs":{"type":"array","items":{"type":"object","properties":{"quantity":{"type":"string"},"unit":{"type":"string"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["quantity","unit","batchId"],"additionalProperties":false}},"losses":{"type":"array","items":{"type":"object","properties":{"quantity":{"type":"string"},"unit":{"type":"string"},"kind":{"type":"string"}},"required":["quantity","unit","kind"],"additionalProperties":false}},"customFields":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."}}},"required":["recordKind","recordId","kind","reference","stepKey","occurredAt","inputs","outputs","losses","customFields"],"additionalProperties":false}],"description":"One record upstream of the lot: a lot (with its depth from the root), a transport or a receipt (with the lots it carried), or a transformation (inputs, outputs and losses), each with the company’s custom values."}}},"required":["root","truncated","nodes"],"additionalProperties":false,"description":"Everything upstream of a lot with the company’s custom values: the inputs an external system needs to compute a cost per unit. Origonex computes nothing from it."}},"parameters":{}},"paths":{"/tenant":{"get":{"tags":["Tenant"],"summary":"Read the caller’s own tenant","description":"Returns the tenant the authenticated session is scoped to.","x-origonex-scope":"master.read","x-origonex-unpaginated":"The calling workspace: one record.","security":[{"bearerAuth":["master.read"]}],"responses":{"200":{"description":"The caller’s tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"401":{"description":"Missing or invalid auth; see RFC 9457 problem+json","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Tenant"],"summary":"Update the caller’s own tenant","description":"Mutates the public mutable subset of Tenant (displayName / primaryCountry). Plan changes go through sales/admin, never this endpoint.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantPatch"}}}},"responses":{"200":{"description":"Updated tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"401":{"description":"Missing or invalid auth","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/parties":{"get":{"tags":["Party"],"summary":"List parties","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","enum":["supplier","sub_supplier","transporter","processor","certifier","buyer","smallholder","other"],"description":"Party (legal entity) role in the supply chain"},"required":false,"description":"Party (legal entity) role in the supply chain","name":"kind","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{2}$/u"},"required":false,"name":"country","in":"query"},{"schema":{"type":"string","enum":["not_started","pending","approved","rejected","expired"],"description":"KYC / KYB status: per-tenant onboarding flow"},"required":false,"description":"KYC / KYB status: per-tenant onboarding flow","name":"kycStatus","in":"query"},{"schema":{"type":"string","enum":["clear","weak","probable","confirmed","unscreenable"],"description":"Sanctions screening outcome, produced by the screening package (OFAC / EU / UK / UN / etc.). `unscreenable` is not a severity band: it means no comparison was possible, because the matcher scores Latin transliterations and the party's name is in a script it cannot read. Treat it as non-clear and requiring human review, never as an outcome."},"required":false,"description":"Sanctions screening outcome, produced by the screening package (OFAC / EU / UK / UN / etc.). `unscreenable` is not a severity band: it means no comparison was possible, because the matcher scores Latin transliterations and the party's name is in a script it cannot read. Treat it as non-clear and requiring human review, never as an outcome.","name":"sanctionsMatch","in":"query"},{"schema":{"type":"string","pattern":"^\\d{1,10}$/u"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only records changed at or after this instant (read from a 5-minute overlap before it; dedupe by id). Combine with `includeDeleted=true` to learn of deletions."},"required":false,"description":"Incremental sync: only records changed at or after this instant (read from a 5-minute overlap before it; dedupe by id). Combine with `includeDeleted=true` to learn of deletions.","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"}],"responses":{"200":{"description":"Page of parties (active only; soft-deleted excluded)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartyList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Party"],"summary":"Create a party","description":"Creates a legal entity in the supply chain. kycStatus starts not_started and is decided by a person in the company (its Supervisor, with a second factor) after reviewing the documents; a sanctions screen never approves or rejects it. sanctionsMatch starts clear and comes from the sanctions screening. Neither is written by this endpoint.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartyCreate"}}}},"responses":{"201":{"description":"Created","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Party"}}}},"400":{"description":"legalRegistrationNumber is not a valid tax id for the declared country","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/parties/{id}":{"get":{"tags":["Party"],"summary":"Read a party by id","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The party","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Party"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Party"],"summary":"Update a party","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartyPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Party"}}}},"400":{"description":"legalRegistrationNumber is not a valid tax id for the declared country","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Party"],"summary":"Soft-delete a party","description":"Deactivates the party (active=false). Hard deletion never happens: auditor scope retains the row for the regulatory retention window.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"204":{"description":"Deactivated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/plots":{"get":{"tags":["Plot"],"summary":"List plots","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"ownerPartyId","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{2}$/u"},"required":false,"name":"country","in":"query"},{"schema":{"type":"string","pattern":"^\\d{1,10}$/u"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only records changed at or after this instant (read from a 5-minute overlap before it; dedupe by id). Combine with `includeDeleted=true` to learn of deletions."},"required":false,"description":"Incremental sync: only records changed at or after this instant (read from a 5-minute overlap before it; dedupe by id). Combine with `includeDeleted=true` to learn of deletions.","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"}],"responses":{"200":{"description":"Page of plots (active only; soft-deleted excluded)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlotList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Plot"],"summary":"Create a plot","description":"Creates a new plot of land, geolocated by a `polygon` or by a single `point` with `declaredAreaHectares` (EUDR Art. 9(1)(d): a point up to 4 ha; Art. 2(28): any size for a cattle establishment, i.e. `commodities: [\"cattle\"]`). areaHectares (measured for a polygon, declared for a point) and centroid are server-computed; the response carries them. The plot owner (`ownerPartyId`) must be a producing party (kind supplier, sub_supplier, processor, smallholder). Until 2026-12-23 a non-producing owner (certifier, transporter, buyer) is still accepted, and that response carries `Deprecation`, `Sunset` and `Link` headers; from 2026-12-23T00:00:00.000Z it is refused with 422 `plot-owner-not-producer`. Changelog: https://origonex.com/docs/changelog#2026-09-24-plot-owner-must-be-a-producer.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlotCreate"}}}},"responses":{"201":{"description":"Created","headers":{"Deprecation":{"schema":{"type":"string","description":"RFC 9745. Present only when the request set a non-producing owner: that use is deprecated since this date (`@<unix seconds>`).","example":"@1790208000"},"required":false,"description":"RFC 9745. Present only when the request set a non-producing owner: that use is deprecated since this date (`@<unix seconds>`)."},"Sunset":{"schema":{"type":"string","description":"RFC 8594. Present only with `Deprecation`: from this date a non-producing owner is refused (422).","example":"Wed, 23 Dec 2026 00:00:00 GMT"},"required":false,"description":"RFC 8594. Present only with `Deprecation`: from this date a non-producing owner is refused (422)."},"Link":{"schema":{"type":"string","description":"Present only with `Deprecation`: the changelog entry, as `rel=\"deprecation\"` (RFC 9745) and `rel=\"sunset\"` (RFC 8594)."},"required":false,"description":"Present only with `Deprecation`: the changelog entry, as `rel=\"deprecation\"` (RFC 9745) and `rel=\"sunset\"` (RFC 8594)."},"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plot"}}}},"400":{"description":"Referenced owner party is unknown or belongs to another tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"A point plot the geolocation rule refuses (no declared area, or more than 4 ha for anything but a cattle establishment: `PointPlotRefused`), or, from 2026-12-23T00:00:00Z, an `ownerPartyId` that is not a producer (certifier, transporter, buyer). Nothing is written.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PointPlotRefused"},{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/plots/{id}":{"get":{"tags":["Plot"],"summary":"Read a plot by id","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The plot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plot"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Plot"],"summary":"Update a plot","description":"Submitting a new polygon re-versions the geometry (the change is recorded in the audit ledger; area + centroid are recomputed); on a point plot it converts the plot to a polygon. `point` / `declaredAreaHectares` restate a point plot under the same rule as creation; a polygon plot is never turned into a point (422). The plot owner (`ownerPartyId`) must be a producing party (kind supplier, sub_supplier, processor, smallholder). Until 2026-12-23 a non-producing owner (certifier, transporter, buyer) is still accepted, and that response carries `Deprecation`, `Sunset` and `Link` headers; from 2026-12-23T00:00:00.000Z it is refused with 422 `plot-owner-not-producer`. Changelog: https://origonex.com/docs/changelog#2026-09-24-plot-owner-must-be-a-producer. A patch that does not change `ownerPartyId` (absent, or the owner the plot already has) is not judged by this rule.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlotPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"Deprecation":{"schema":{"type":"string","description":"RFC 9745. Present only when the request set a non-producing owner: that use is deprecated since this date (`@<unix seconds>`).","example":"@1790208000"},"required":false,"description":"RFC 9745. Present only when the request set a non-producing owner: that use is deprecated since this date (`@<unix seconds>`)."},"Sunset":{"schema":{"type":"string","description":"RFC 8594. Present only with `Deprecation`: from this date a non-producing owner is refused (422).","example":"Wed, 23 Dec 2026 00:00:00 GMT"},"required":false,"description":"RFC 8594. Present only with `Deprecation`: from this date a non-producing owner is refused (422)."},"Link":{"schema":{"type":"string","description":"Present only with `Deprecation`: the changelog entry, as `rel=\"deprecation\"` (RFC 9745) and `rel=\"sunset\"` (RFC 8594)."},"required":false,"description":"Present only with `Deprecation`: the changelog entry, as `rel=\"deprecation\"` (RFC 9745) and `rel=\"sunset\"` (RFC 8594)."},"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plot"}}}},"400":{"description":"Referenced owner party is unknown or belongs to another tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"A point change the geolocation rule refuses (`PointPlotRefused`), or, from 2026-12-23T00:00:00Z, a change of `ownerPartyId` to a party that is not a producer. Nothing is written.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PointPlotRefused"},{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Plot"],"summary":"Soft-delete a plot","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"204":{"description":"Deactivated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/tokens/{publicToken}/proof":{"get":{"tags":["Tokens"],"summary":"Resolve an anchored Token to its on-chain proof reference","description":"Returns the chain, contract address, token id / Merkle root, transaction hash, block number, and confirmation timestamp for a given Token public token. Public, unauthenticated: the proof is the trust artifact. The path segment is the high-entropy `publicToken` (256-bit, base64url), NOT the internal cuid id: the id is enumerable, the publicToken is not.","x-origonex-scope":"public","x-origonex-unpaginated":"One proof of one token.","security":[],"parameters":[{"schema":{"type":"string","format":"public-token","pattern":"^[A-Za-z0-9_-]{1,64}$/u","description":"256-bit CSPRNG capability token (base64url, ~43 chars)"},"required":true,"description":"256-bit CSPRNG capability token (base64url, ~43 chars)","name":"publicToken","in":"path"}],"responses":{"200":{"description":"Token proof reference","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenProof"}}}},"401":{"description":"Missing or invalid credentials","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"403":{"description":"Authenticated but not permitted to read this token","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"404":{"description":"No token matches the given public token","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"The path parameter failed validation","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/batches/{batchId}/label":{"get":{"tags":["Label"],"summary":"Resolve the mark a batch should carry","description":"Returns the payload URL a printed or encoded mark for this batch must carry, plus the facts printed beside it. `payload` is null when the batch has never been sealed: there is nothing truthful to encode yet, which is a state rather than an error. Request `mode=gs1_digital_link` with a `gtin` to get a GS1 Digital Link that retail POS scanners resolve; without a GTIN the response falls back to the verifier URL rather than emitting an unresolvable Digital Link.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The label of one lot.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"path"},{"schema":{"type":"string","enum":["verifier","gs1_digital_link"]},"required":false,"name":"mode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{8}$|^\\d{12}$|^\\d{13}$|^\\d{14}$/u"},"required":false,"name":"gtin","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":20},"required":false,"name":"serial","in":"query"}],"responses":{"200":{"description":"The mark payload and the batch facts printed with it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No batch with that id in the caller’s tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"A parameter failed validation (including a malformed GTIN)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/batches/{batchId}/label.svg":{"get":{"tags":["Label"],"summary":"Render the batch label as vector artwork","description":"The whole label (mark and text) as a self-contained SVG in millimetre units, for pre-press artwork or a raster-only driver that scales it to the print head. Resolution-independent: nothing is resampled from a fixed bitmap.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The label of one lot, as SVG.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"path"},{"schema":{"type":"string","enum":["verifier","gs1_digital_link"]},"required":false,"name":"mode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{8}$|^\\d{12}$|^\\d{13}$|^\\d{14}$/u"},"required":false,"name":"gtin","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":20},"required":false,"name":"serial","in":"query"},{"schema":{"type":"string","enum":["thermal_50x30","dymo_54x25","brother_dk_62x100","zebra_102x152","a4_sheet_48mm"]},"required":false,"name":"preset","in":"query"},{"schema":{"type":"string","enum":["L","M","Q","H"]},"required":false,"name":"ecc","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"showPayloadUrl","in":"query"}],"responses":{"200":{"description":"SVG document","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"image/svg+xml":{"schema":{"type":"string"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No batch with that id in the caller’s tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"409":{"description":"The batch is not sealed, so it has no mark to render","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"A parameter failed validation (including a malformed GTIN)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/batches/{batchId}/label.zpl":{"get":{"tags":["Label"],"summary":"Render the batch label as ZPL II","description":"ZPL II for a Zebra-compatible printer at the packing line. The symbol is sent as text for the printer firmware to draw (`^BQ`), so it lands exactly on the dot grid instead of being resampled, and `^PQ` repeats the label in the printer rather than in the caller.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The label of one lot, as ZPL.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"path"},{"schema":{"type":"string","enum":["verifier","gs1_digital_link"]},"required":false,"name":"mode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{8}$|^\\d{12}$|^\\d{13}$|^\\d{14}$/u"},"required":false,"name":"gtin","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":20},"required":false,"name":"serial","in":"query"},{"schema":{"type":"string","enum":["thermal_50x30","dymo_54x25","brother_dk_62x100","zebra_102x152","a4_sheet_48mm"]},"required":false,"name":"preset","in":"query"},{"schema":{"type":"string","enum":["L","M","Q","H"]},"required":false,"name":"ecc","in":"query"},{"schema":{"type":"number"},"required":false,"name":"dpi","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":10000},"required":false,"name":"copies","in":"query"}],"responses":{"200":{"description":"ZPL II program","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No batch with that id in the caller’s tenant","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"409":{"description":"The batch is not sealed, so it has no mark to render","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"422":{"description":"A parameter failed validation (including a malformed GTIN)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["type","title","status","code"]}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/status":{"get":{"tags":["Custody"],"summary":"Whether chain-of-custody is enabled for the calling tenant","description":"Answers 200 when chain-of-custody resources are available to the caller, and 404 when they are not: the same response an unknown path gets.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"A yes/no probe: is chain-of-custody on for this workspace.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"Chain-of-custody is enabled","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyStatus"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/templates":{"get":{"tags":["Custody"],"summary":"The chain each commodity typically runs through","description":"The stage template of each of the seven EUDR commodities: its stages in chain order (with the units, documents and kinds of site each typically has, and the tolerance on a receipt), the transformations between stages with their expected yield and losses, and the link where the chain is most exposed.\n\nReference data, the same for every workspace, versioned: a record stores the `version` it was checked against. A template guides: a yield outside its range is recorded and flagged, never refused.\n\nThe yield ranges, receipt tolerances (`shrink`) and grading thresholds are REFERENCE DEFAULTS, not regulatory tolerances. Each carries a `source`: the published source of its reference values, or `origonex_default` where Origonex chose the value.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The fixed catalogue of stage templates, one per commodity: shipped with the code, not stored data, so there is nothing to sync.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"Every stage template","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyStageTemplateList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Chain-of-custody is not enabled for this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/templates/{commodity}":{"get":{"tags":["Custody"],"summary":"The chain one commodity typically runs through","description":"The stage template of one commodity. Templates exist for wood, cattle, coffee, cocoa, palm_oil, soy, rubber; any other commodity answers 404.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"commodity","in":"path"}],"responses":{"200":{"description":"The stage template","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyStageTemplate"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No stage template for this commodity, or chain-of-custody is not enabled for this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/tags/resolve":{"post":{"tags":["Custody"],"summary":"Resolve a scanned tag to the lot it identifies","description":"Takes what a scanner read (a QR or DataMatrix payload, an NFC chip value or the URI it carries, an RFID EPC) and answers which lot it identifies. A POST, not a GET, because the value is often a capability-bearing URL that must not land in access logs.\n\nAccepted, first match wins: (1) a tag issued in this workspace with the same `kind` and exact `value`; (2) the `tagValue` of one of this workspace’s live vehicles, exactly, answered as `vehicle` (with its id, plate and kind), not a lot; (3) our public proof link `https://verify.origonex.com/t/{workspace}/{token}` or `https://verify.origonex.com/{token}`, resolved to the lot the proof covers; (4) our GS1 Digital Link `https://verify.origonex.com/dl/01/{gtin}/10/{lot}[/21/{serial}]?ox={token}`, resolved on `ox` only; a Digital Link without `ox`, or with an empty or malformed one, is not a mark we issued; (5) a product unit’s page `https://verify.origonex.com/u/{key}` (or under `/t/{workspace}/`), or its Digital Link carrying the unit’s key as `ox` with the unit’s own GTIN and serial (AI 21), resolved to the unit’s lot. Links on any other host, including other GS1 resolvers, answer `unknown`.\n\n`status` is `resolved` (with the lot), `revoked` (the mark was withdrawn; `revokedAt` says when), `unbound` (a tag of this workspace not on any lot; link it with `/custody/tags/{id}/bind`), `vehicle` (a vehicle’s tag) or `unknown`. A tag or proof belonging to another workspace answers `unknown`, identically to a value nobody issued.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResolveRequest"}}}},"responses":{"200":{"description":"What the scan identifies","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResolution"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Chain-of-custody is not enabled for this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/tags/{id}/bind":{"post":{"tags":["Custody"],"summary":"Put a tag on a lot","description":"Links a tag of this workspace to a lot, recorded in the audit trail as `tag.bound`. Idempotent on the same lot. A tag already on another lot is refused with 409 unless `move` is true. A revoked tag is refused with 409: a withdrawn mark does not come back into use by being re-linked.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagBindRequest"}}}},"responses":{"200":{"description":"The tag, now on the lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BoundTag"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field, or the tag is NFC / RFID and the plan does not include NFC / RFID tracking (`PLAN_FEATURE_LOCKED:nfcRfidTracking`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"404":{"description":"No such tag in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"409":{"description":"The tag is revoked, or on another lot and `move` was not set","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"No such lot in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/tags/link":{"post":{"tags":["Custody"],"summary":"Link what was scanned to a lot","description":"Links a scanned `(kind, value)` to a lot in one step: the tag is issued on the lot (audited as `tag.created`) when this workspace does not hold it yet, and bound under the rules of `/custody/tags/{id}/bind` (audited as `tag.bound`) when it does. Safe to retry: a repeat on the same lot changes nothing.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagLinkRequest"}}}},"responses":{"200":{"description":"The tag, now on the lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BoundTag"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field, or the tag is NFC / RFID and the plan does not include NFC / RFID tracking (`PLAN_FEATURE_LOCKED:nfcRfidTracking`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"404":{"description":"No such tag in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"409":{"description":"The tag is revoked, or on another lot and `move` was not set","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"No such lot in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/events/{id}/correction":{"post":{"tags":["Custody"],"summary":"Correct a recorded event","description":"Recorded events are never edited or deleted. A correction is a NEW event that supersedes the one in the path; both stay in the history, labelled, and the public page and the phones show the correction only. Recorded in the audit trail as `event.corrected`.\n\nWhat the body leaves out is kept from the event being corrected. `payload`, when sent, is the whole new payload for the event type, not a patch. The type, the subject, the location and the attachments are always kept: an event of the wrong type, or recorded against the wrong subject, is retracted and recorded again. `reason` is required.\n\nCorrecting or retracting an `audit` or `inspection` event also needs the audit & verification capability, a `mass_balance_credit` or `mass_balance_claim` event compliance-output approval, and a `geometry_repaired` event master-data write: the same capability that records it (403 otherwise).\n\nAn event is superseded at most once; correct the latest version.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventCorrection"}}}},"responses":{"201":{"description":"The new event, which supersedes the one named in the path","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEvent"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field, or the event is an engine’s own record of a step (a transport’s transition) or the correction would write a field only that engine writes (`EVENT_ENGINE_OWNED`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"404":{"description":"No such event in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"409":{"description":"The event was already corrected or retracted (`EVENT_ALREADY_SUPERSEDED`), or it is itself a retraction (`EVENT_IS_RETRACTION`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"The payload does not fit the event type (`INVALID_EVENT_PAYLOAD`), the time is out of bounds (`OCCURRED_AT_*`), or the correction changes nothing (`EVENT_CORRECTION_UNCHANGED`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/events/{id}/retraction":{"post":{"tags":["Custody"],"summary":"Retract a recorded event","description":"Withdraws a recorded event: it leaves the public page and the phones, and the history keeps the retraction, with who, when and why, in its place. Recorded in the audit trail as `event.retracted`. A retraction cannot itself be corrected or retracted.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventRetraction"}}}},"responses":{"201":{"description":"The new event, which supersedes the one named in the path","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEvent"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field, or the event is an engine’s own record of a step (a transport’s transition) or the correction would write a field only that engine writes (`EVENT_ENGINE_OWNED`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"404":{"description":"No such event in this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"409":{"description":"The event was already corrected or retracted (`EVENT_ALREADY_SUPERSEDED`), or it is itself a retraction (`EVENT_IS_RETRACTION`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"The payload does not fit the event type (`INVALID_EVENT_PAYLOAD`), the time is out of bounds (`OCCURRED_AT_*`), or the correction changes nothing (`EVENT_CORRECTION_UNCHANGED`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/events":{"get":{"tags":["Custody"],"summary":"The event history of a subject","description":"Every recorded version of the events on one subject, oldest first: `kind` is `record`, `correction` (of `supersedesEventId`) or `retraction`; `correctedById` is set on a version a later correction replaced. A retracted event is not listed; its retraction is, at the same time. Keyset-paged: pass `nextCursor` back as `cursor`.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["plot","batch","shipment","party","site","transport","certificate","document","dds"]},"required":true,"name":"subjectType","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"subjectId","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"}],"responses":{"200":{"description":"One page of the history","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventHistory"}}}},"400":{"description":"The cursor is not one this API issued","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not read field capture","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Record an event, signed on a device or not","description":"Records a custody event with the checks every capture gets: the subject is a live record of this workspace, the time is believable, the place is on the globe, every attachment is a live document here, the payload fits the type, and the caller may record the type. Recorded in the audit trail as `event.created`, with the fingerprint of the event’s content.\n\n`deviceSignature` is the phone’s signature over the event and the bytes of its files (see the schema for the exact bytes signed). The server recomputes what was signed from the event as it records it, checks it against the caller’s registered key, and records the verdict with the event (`deviceSignature` in the answer). A verdict other than `verified` FLAGS the event: it is recorded, never refused.\n\n`id` is the client’s. The same id for the same event answers the event it recorded (`replayed: true`, 200); for a different event, 409 `EVENT_ID_TAKEN`.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventCreation"}}}},"responses":{"200":{"description":"The id had already recorded this event","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventRecorded"}}}},"201":{"description":"The event, recorded","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEventRecorded"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field, or record this type","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The id names another event (`EVENT_ID_TAKEN`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"422":{"description":"The event was refused: a subject or document that is not this workspace’s (`SUBJECT_NOT_FOUND`, `DOCUMENT_REF_NOT_FOUND`), the payload (`INVALID_EVENT_PAYLOAD`), the time (`OCCURRED_AT_*`) or the place (`INVALID_LOCATION`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/events/{id}":{"get":{"tags":["Custody"],"summary":"Read one recorded version of an event","description":"One version as the history lists it: `kind` is `record`, `correction` or `retraction`; `correctedById` names the version that replaced it, if one did.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyEvent"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No event of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/sites":{"get":{"tags":["Custody"],"summary":"List sites","description":"Sites in (updatedAt, id) order. Pass the previous page's `nextCursor` as `cursor` to continue. For incremental sync pass `updatedSince` (and `includeDeleted=true` to learn of deletions): the server re-reads from 5 minutes before it, because writes commit out of `updatedAt` order, so the same site can come back in consecutive syncs; dedupe by `id`. A page walk alone is not a complete sync; finish it with an `updatedSince` read. A cursor that was not produced by this API is refused with 400.","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"},{"schema":{"type":"string","enum":["yard","warehouse","silo","sawmill","factory","mill","slaughterhouse","cooperative","port","farm","other","collection_point","refinery_crusher","feedlot","terminal","drying_station"],"description":"What kind of place the site is"},"required":false,"description":"What kind of place the site is","name":"kind","in":"query"}],"responses":{"200":{"description":"A page of sites","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Register a site","description":"Registers a place where custody happens. `ownerPartyId` must be one of your live parties and `responsibleUserId` an active member of your workspace; anything else is refused with 422.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCreate"}}}},"responses":{"201":{"description":"Registered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"A reference is not usable by this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/sites/{id}":{"get":{"tags":["Custody"],"summary":"Read a site","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The site","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such site","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Update a site","description":"Absent fields are kept; `null` clears an optional field.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePatch"}}}},"responses":{"200":{"description":"Updated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Site"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such site","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"422":{"description":"A reference is not usable by this workspace","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Custody"],"summary":"Delete a site","description":"Soft delete: the site disappears from lists and can no longer be named by new records, and stays readable in incremental sync (`includeDeleted=true`) with `deletedAt` set.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such site","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SiteProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/lots":{"get":{"tags":["Custody"],"summary":"List lots","description":"The workspace’s lots in `(updatedAt, id)` order: the feed an ERP syncs from. `includeDeleted=true` with `updatedSince` also returns archived lots (with `deletedAt`), so an incremental reader learns of them.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id.","name":"updatedSince","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":64},"required":false,"name":"commodity","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"}],"responses":{"200":{"description":"A page of lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLotPage"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Form a lot","description":"Forms a lot of one commodity from its producer, with its origin plots and lineage, with the same checks as the app (every reference resolves in this workspace, mass balance against parents, the lot code unique, the unit fits the commodity and, with `stage`, the stage). Recorded in the audit trail as `batch.created`.\n\nIdempotent by the body’s `id` (a lot id the client chose, 16 to 64 url-safe characters): the same lot again answers the lot already made; the same id with a different lot is 409. The `Idempotency-Key` header works too.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLotCreate"}}}},"responses":{"201":{"description":"The lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLot"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not create master data","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The lot code or the lot id is taken by a different lot (`state_conflict`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"422":{"description":"Refused: a reference that does not resolve, a quantity or stage that does not fit","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/lots/{id}":{"get":{"tags":["Custody"],"summary":"Read a lot","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLot"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No live lot of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/certificates":{"get":{"tags":["Custody"],"summary":"List certificates","description":"The workspace’s certificates (held by a party, a plot, a site or a lot) in `(updatedAt, id)` order. `updatedAt` moves with a registry check too.","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id.","name":"updatedSince","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40},"required":false,"name":"certifier","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40},"required":false,"name":"subjectType","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"subjectId","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"}],"responses":{"200":{"description":"A page of certificates","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCertificateRecordPage"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Record a certificate","description":"Records a certificate the holder presented: the scheme, its number, what it covers and its validity (`validUntil` on or after `validFrom`). Recorded in the audit trail as `certificate.imported`. Check it against the certifier’s registry with `POST /custody/certificates/{id}/registry-check`.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCertificateCreate"}}}},"responses":{"201":{"description":"The certificate","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCertificateRecord"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not create master data","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Refused","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/certificates/{id}":{"get":{"tags":["Custody"],"summary":"Read a certificate","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The certificate","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCertificateRecord"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No live certificate of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/claims":{"get":{"tags":["Custody"],"summary":"List claim declarations","description":"Every claim declaration of the workspace (what a supplier’s invoice stated about a lot) in `(createdAt, id)` order. A declaration is never edited: a correction is a new one naming the one it corrects in `supersedesId`. Declare one with `POST /custody/batches/{id}/claims`; a lot’s current claims are at `GET /custody/batches/{id}/claims`.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A declaration is never edited: this keeps the ones recorded since."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A declaration is never edited: this keeps the ones recorded since.","name":"updatedSince","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"query"}],"responses":{"200":{"description":"A page of declarations","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyClaimDeclarationPage"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/claims/{id}":{"get":{"tags":["Custody"],"summary":"Read a claim declaration","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The declaration","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyClaimDeclaration"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No declaration of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyRecordProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/vehicles":{"get":{"tags":["Custody"],"summary":"List vehicles","description":"Vehicles in (updatedAt, id) order. Pass the previous page's `nextCursor` as `cursor` to continue. For incremental sync pass `updatedSince` (and `includeDeleted=true` to learn of deletions): the server re-reads from 5 minutes before it, so the same vehicle can come back in consecutive syncs; dedupe by `id`. A cursor that was not produced by this API is refused with 400.","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"},{"schema":{"type":"string","enum":["truck","trailer","boat","wagon","other"],"description":"What the vehicle is: truck, trailer, boat, rail wagon, other"},"required":false,"description":"What the vehicle is: truck, trailer, boat, rail wagon, other","name":"kind","in":"query"}],"responses":{"200":{"description":"A page of vehicles","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Register a vehicle","description":"Registers a truck, trailer, boat or rail wagon. The plate is stored normalised (upper case, without spaces, hyphens or dots) and is unique among the live vehicles of the workspace. `capacity` goes with `capacityUnit`; for every mass unit the number is kilograms. `tagValue` is what a QR, barcode or chip on the vehicle carries: `POST /v1/custody/tags/resolve` answers `vehicle` for it.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleCreate"}}}},"responses":{"201":{"description":"Registered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vehicle"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Another live vehicle of this workspace already has this plate (`VEHICLE_PLATE_TAKEN`) or tag value (`VEHICLE_TAG_TAKEN`, also when a lot tag holds it)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"422":{"description":"The carrier is not a live party of this workspace, the plate has no letters or digits left once normalised, or a capacity has no unit","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/vehicles/{id}":{"get":{"tags":["Custody"],"summary":"Read a vehicle","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The vehicle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vehicle"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such vehicle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Update a vehicle","description":"Absent fields are kept; `null` clears an optional field.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehiclePatch"}}}},"responses":{"200":{"description":"Updated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vehicle"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such vehicle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"409":{"description":"Another live vehicle of this workspace already has this plate (`VEHICLE_PLATE_TAKEN`) or tag value (`VEHICLE_TAG_TAKEN`, also when a lot tag holds it)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"422":{"description":"The carrier is not a live party of this workspace, the plate has no letters or digits left once normalised, or a capacity has no unit","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Custody"],"summary":"Delete a vehicle","description":"Soft delete: the vehicle leaves lists, its plate and tag value become free, and it stays readable in incremental sync (`includeDeleted=true`) with `deletedAt` set.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such vehicle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/VehicleProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/drivers":{"get":{"tags":["Custody"],"summary":"List drivers","description":"Drivers in (updatedAt, id) order, each with the identity the personal-data vault holds now. Same paging and incremental-sync contract as vehicles and sites: pass the previous page's `nextCursor` as `cursor`; `updatedSince` re-reads from 5 minutes before it, dedupe by `id`. A driver whose identity was corrected or erased comes back with a new `updatedAt`.","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"}],"responses":{"200":{"description":"A page of drivers","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Register a driver","description":"Registers a driver. `identity` (name, document, licence) is sealed in the workspace's erasable personal-data vault; the driver record and the audit trail keep only `personalDataRef`. The workspace is the controller of this personal data.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverCreate"}}}},"responses":{"201":{"description":"Registered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Driver"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The carrier is not a live party of this workspace, or a CPF fails its check digits","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/drivers/{id}":{"get":{"tags":["Custody"],"summary":"Read a driver","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The driver","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Driver"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such driver","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Change the carrier of a driver","description":"Changes `carrierPartyId` (`null` = the workspace’s own staff). The identity is corrected with `PUT /custody/drivers/{id}/identity`.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Driver"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such driver","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"422":{"description":"The carrier is not a live party of this workspace, or a CPF fails its check digits","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Custody"],"summary":"Delete a driver","description":"Soft delete: the driver leaves lists and stays readable in incremental sync with `deletedAt` set. The identity stays in the vault until the workspace erases it or the retention purge removes the record.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such driver","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/drivers/{id}/identity":{"put":{"tags":["Custody"],"summary":"Correct a driver's identity","description":"Replaces the whole identity held for the driver: a rectification of the vault entry: the reference stays the same, so every record that names the driver shows the corrected identity. Requires `master_data:approve`. Refused with 409 once the person was erased (`PERSONAL_DATA_ERASED`) or while a legal hold is open (`LEGAL_HOLD_ACTIVE`).","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverIdentity"}}}},"responses":{"200":{"description":"Corrected","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Driver"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such driver","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"409":{"description":"The person was erased, or a legal hold is open","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"422":{"description":"The carrier is not a live party of this workspace, or a CPF fails its check digits","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/DriverProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transformations":{"post":{"tags":["Custody"],"summary":"Record a transformation","description":"Records N input lots, each with the quantity it consumes, turning into M new output lots plus losses by kind, at a site: a split, a merge, a process, a pack or a slaughter. Each output becomes a lot. Consuming more of a lot than it still holds (summed over every transformation) is refused with 409, and so is a `reference` (the company’s own number for the step, S-0388) another step already carries; outputs above the inputs, or a malformed record, with 422. A yield outside the commodity template’s range is recorded and listed in `alerts`, not refused. Send an `id` to make a retry safe: the same id with the same inputs returns the stored record with 200.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationRecord"}}}},"responses":{"200":{"description":"Already recorded with this id (a retry)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransformation"}}}},"201":{"description":"Recorded","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransformation"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A lot does not hold that much any more, or the id names another record","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationProblem"}}}},"422":{"description":"Refused: impossible or malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List transformations","description":"Transformations in (recordedAt, id) order. Pass the previous page's `nextCursor` as `cursor` to continue; `batchId` keeps only the steps a lot went into or came out of. A cursor that was not produced by this API is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"query"},{"schema":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f]+$/u","description":"CUS-607: only the step with exactly this reference","examples":["T-2091"]},"required":false,"description":"CUS-607: only the step with exactly this reference","name":"reference","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of transformations","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transformations/{id}":{"get":{"tags":["Custody"],"summary":"Read a transformation","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The transformation","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransformation"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transformation","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransformationProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports":{"post":{"tags":["Custody"],"summary":"Create a transport","description":"Creates one leg: carrier, vehicle, driver, origin and destination (each a site or a party), planned times, an optional route. With `loads` the lots go on board in the same call (status `loaded`), and with `actualDepartureAt` the truck leaves too (`in_transit`): the phone’s \"load and leave\", offline. A `reference` (the company’s own number for the trip, T-2091) another trip already carries is refused with 409. Loading more of a lot than it still holds at the origin (not already loaded, consumed or transformed) is refused with 409. The loaded total is compared with the weighing (net = gross − tare, or a measured volume): outside the tolerance it is recorded and listed in `alerts`, not refused. Send an `id` to make a retry safe: the same id for the same trip returns the stored transport with 200.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportCreate"}}}},"responses":{"200":{"description":"Already created with this id (a retry)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"201":{"description":"Created","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List transports","description":"Transports in (updatedAt, id) order. Pass the previous page's `nextCursor` as `cursor` to continue. `status=loaded,in_transit&destinationSiteId=…` is the trips on their way to a site; `batchId` keeps the transports that carry a lot; `updatedSince` reads what changed. A cursor that was not produced by this API is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","pattern":"^(?:planned|loaded|in_transit|delivered|cancelled)(?:,(?:planned|loaded|in_transit|delivered|cancelled))*$/u"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"originSiteId","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"destinationSiteId","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"query"},{"schema":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f]+$/u","description":"CUS-607: only the trip with exactly this reference","examples":["T-2091"]},"required":false,"description":"CUS-607: only the trip with exactly this reference","name":"reference","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A page of transports","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports/{id}":{"get":{"tags":["Custody"],"summary":"Read a transport","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Edit a planned transport","description":"Changes the header (carrier, vehicle, driver, places, plan, route, shipment, note, reference) while the transport is planned. From `loaded` on the header is fixed: 409.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportPatch"}}}},"responses":{"200":{"description":"Done, or already done: a retry answers the transport as it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports/{id}/load":{"post":{"tags":["Custody"],"summary":"Load a planned transport","description":"Puts the lots on board, each with its quantity, and records the weighing. Status `planned` → `loaded`; the header is fixed from here on.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportLoad"}}}},"responses":{"200":{"description":"Done, or already done: a retry answers the transport as it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports/{id}/depart":{"post":{"tags":["Custody"],"summary":"The truck leaves","description":"Status `loaded` → `in_transit`, with the actual departure time.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportDepart"}}}},"responses":{"200":{"description":"Done, or already done: a retry answers the transport as it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports/{id}/deliver":{"post":{"tags":["Custody"],"summary":"The truck arrives","description":"Status `in_transit` → `delivered`, with the actual arrival time. What was received is the receipt.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportDeliver"}}}},"responses":{"200":{"description":"Done, or already done: a retry answers the transport as it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/transports/{id}/cancel":{"post":{"tags":["Custody"],"summary":"Cancel a transport","description":"Any status before `delivered` → `cancelled`, with a reason. The lots it carried count as available again.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransportCancel"}}}},"responses":{"200":{"description":"Done, or already done: a retry answers the transport as it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTransport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"409":{"description":"A lot does not hold that much at the origin, the transport’s status does not allow the step, or a replay names other lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTransportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/receipts":{"post":{"tags":["Custody"],"summary":"Receive a transport","description":"Receives a transport at its destination site: when, the weighing there, the ticket, the photos (documents already filed against the transport), and for each lot on board what arrived and what was accepted: `accepted`, `partial` (say how much per lot) or `rejected`, with a reason for the last two. The transport becomes `delivered`. What was accepted is placed at the site, and custody passes to the site and the party that owns it; what was refused goes back to the origin; the difference between sent and received is the transit loss. A divergence beyond the directional band of the lot’s stage is recorded, listed in `alerts` and raised in the compliance queue, never refused. Send an `id` to make a retry safe.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptRecord"}}}},"responses":{"200":{"description":"Already received with this id (a retry)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptRecorded"}}}},"201":{"description":"Received","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptRecorded"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such transport","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptProblem"}}}},"409":{"description":"The transport cannot be received (planned, cancelled, received already), or the id names another receipt","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptProblem"}}}},"422":{"description":"Refused: impossible, malformed, or not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List receipts","description":"Receipts in (createdAt, id) order. Pass the previous page's `nextCursor` as `cursor` to continue. `siteId` is what a site received; `batchId` the receipts of a lot. A cursor that was not produced by this API is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"siteId","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"transportId","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"batchId","in":"query"},{"schema":{"type":"string","enum":["accepted","partial","rejected"],"description":"accepted: everything that arrived; partial: part of it (say how much per lot); rejected: none of it."},"required":false,"description":"accepted: everything that arrived; partial: part of it (say how much per lot); rejected: none of it.","name":"outcome","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of receipts","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/receipts/{id}":{"get":{"tags":["Custody"],"summary":"Read a receipt","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The receipt","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyReceipt"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such receipt","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyReceiptProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/verification":{"get":{"tags":["Custody"],"summary":"Check a lot's chain of custody","description":"Recomputes the content fingerprint of every record upstream of the lot (the events recorded on each lot, the transformations that made them and their lines, the transports that carried a lot with their load lines, events and receipts, and the documents) from the records as they are now, and compares each with the fingerprint stored with it, with the one the audit trail recorded when it was written, and with the lot’s last chain seal. `ok` is true when nothing differs and the whole chain was read; otherwise `divergences` names each record that differs (`recordType`, `id`) and where (`row`, `ledger`, `chain`, `seal`). A record the last seal covered that was deleted through the application, or that the chain no longer reaches because a link was removed through it, is listed in `departures` when the audit trail records that act after the seal: it does not count as a difference, and sealing again covers the chain as it is. A record that left without such an entry is a difference. Records written before fingerprints existed are counted in `unhashed` and never as checked. The check reads at most 5 000 lots and 64 links upstream; beyond, `truncated` is true and `ok` false. The check shows the records match the audit trail; it does not by itself prove when they were written.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One lot’s verification report.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The result of the check","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyChainVerification"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyIntegrityProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/seal":{"post":{"tags":["Custody"],"summary":"Seal a lot's chain of custody","description":"Checks the chain as `GET …/verification` does and, only when nothing differs, records a seal over the fingerprints of every record in it. A chain the live seal already covers answers `unchanged` and records nothing; a chain that grew, or that records left without being altered (`departures`), answers `sealed` with a new seal that supersedes the last. A chain where a record differs is refused with 409 and the check that says which; so is a chain larger than one check reads.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"Sealed, or already covered by the live seal","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyChainSealResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyIntegrityProblem"}}}},"409":{"description":"A record of the chain differs, or the chain is larger than one check reads","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyIntegrityProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/timestamps":{"get":{"tags":["Custody"],"summary":"The days of the audit trail timestamped by an independent authority","description":"Newest first. Each day covers the audit-trail entries written since the previous day, in order, and carries their fingerprint. Once a day, the fingerprint of every workspace’s day is sent to an independent RFC 3161 time-stamping authority; `GET /custody/timestamps/{day}` returns what is needed to check a day without Origonex.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":366},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A day is closed once and never changes."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A day is closed once and never changes.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"The stamped days, newest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerDayList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/LedgerTimestampProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/timestamps/{day}":{"get":{"tags":["Custody"],"summary":"Download one day of the audit trail with its independent timestamp","description":"Every audit-trail entry of the day with the content its fingerprint is computed from, the fingerprint of the day, the path from it to the fingerprint the authority stamped, and the authority’s time-stamp token with its certificates. Check it anywhere with `node scripts/verify-timestamp.mts --day <day> --export <file>`: it recomputes every fingerprint from the entries and verifies the token with OpenSSL. The entries are read as they are now, so an entry changed after the day was stamped makes the check fail. `timestamp` is null while the authority has not answered yet. Above 20 000 entries in a day, entries carry their fingerprint only.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"required":true,"description":"ISO 8601 calendar date","name":"day","in":"path"}],"responses":{"200":{"description":"The day","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerDayExport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No entry of this workspace in that day, or the day is not closed yet","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/LedgerTimestampProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/ledger-events/{ledgerEventId}/inclusion-proof":{"get":{"tags":["Custody"],"summary":"The proof that one audit-trail entry is in an independently timestamped day","description":"CUS-301. The entry with the content its fingerprint is computed from, the path from its fingerprint to the fingerprint of its day (hashes only; the other entries are not disclosed), the path on to the fingerprint every workspace’s day shares, and the authority’s time-stamp token over it. Check it anywhere with `node scripts/verify-timestamp.mts --record <file>`. `status` is `open` (no `proof`) while the entry’s day is not closed, and `pending` (a proof whose `timestamp` is null) while the authority has not answered.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The proof of one audit-trail entry.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"ledgerEventId","in":"path"}],"responses":{"200":{"description":"The entry’s proof, or where it stands","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordInclusionResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No audit-trail entry of this workspace with that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/LedgerTimestampProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/inclusion-proofs":{"get":{"tags":["Custody"],"summary":"Where each audit-trail entry of one record stands on the way to a timestamped day","description":"CUS-301. The entries recorded against one subject (a lot, a transport, a receipt…), oldest first, up to 200, each with the day that covers it and whether that day is timestamped yet. The proof of each is `GET /custody/ledger-events/{ledgerEventId}/inclusion-proof`.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One record’s audit-trail entries with where each stands on the way to a timestamped day, computed on read, capped at 200. The entries are immutable; what changes is their day’s stamp, so a client re-reads it rather than syncing it.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"subjectType","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"subjectId","in":"query"}],"responses":{"200":{"description":"The entries","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordProofList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/tag-rolls":{"post":{"tags":["Custody"],"summary":"Issue a roll of loose labels","description":"Creates `count` QR labels (1 to 500) that belong to no lot yet, for a field buyer to link on the spot by scanning (`POST /custody/tags/link`). Each label carries an internal code (`OXL-…`), not a URL. Idempotent on `requestId`: a retry with the same key and count answers the same roll; the same key with another count is a 409.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRollIssueRequest"}}}},"responses":{"200":{"description":"The roll, as created or as a retry found it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRollIssueResponse"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The key names another request","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TagRollProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"The rolls of loose labels, newest first, with what is left on each","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A roll is never edited: `updatedSince` keeps the rolls issued since then; what is left on a roll is read off its labels each time."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A roll is never edited: `updatedSince` keeps the rolls issued since then; what is left on a roll is read off its labels each time.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of rolls, newest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRollList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/tag-rolls/{id}":{"get":{"tags":["Custody"],"summary":"One roll and each of its labels: free, used (with its lot) or withdrawn","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The roll","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRoll"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No roll of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TagRollProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/supply-links":{"get":{"tags":["Custody"],"summary":"The supply links this workspace holds as producer","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of links, in `(updatedAt, id)` order","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Offer an importer a supply link, consenting at once to its scope","description":"The importer is named by its workspace handle. The link shares only the lots listed, only the fields listed that each lot’s visibility policy also opens to importers (omitted: the conservative default), and the due-diligence statements only with `shareDds`. One open link per importer.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkOffer"}}}},"responses":{"201":{"description":"The granted link","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLink"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No active workspace has that handle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"A link with that importer is already open","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"A lot is not this workspace’s, or the link names itself","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/supply-links/{id}/grant":{"post":{"tags":["Custody"],"summary":"Consent to a request, or replace what a granted link shares","description":"The scope REPLACES the previous one: a lot left out stops being visible to the importer on its next read.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkGrant"}}}},"responses":{"200":{"description":"The granted link","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLink"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No link of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"The link was declined or revoked","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"A lot is not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/supply-links/{id}/end":{"post":{"tags":["Custody"],"summary":"Decline a request or revoke a consent","description":"Terminal: the importer reads nothing through the link from this moment on, and a new consent is a new link. Accepted with the chain-of-custody programme off.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkEnd"}}}},"responses":{"200":{"description":"The ended link","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLink"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No link of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"The link had already ended","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/supply-link-requests":{"post":{"tags":["Custody"],"summary":"Ask a producer for a supply link (as the importer)","description":"Shares nothing until the producer grants it.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkRequest"}}}},"responses":{"201":{"description":"The request, as the importer sees it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterSupplyLink"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No active workspace has that handle","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"A link with that producer is already open","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/importer/links/{id}/accept":{"post":{"tags":["Custody"],"summary":"Accept a producer’s offered supply link (as the importer)","description":"An offer shares nothing and counts nowhere until the importer accepts it; from then on the link shares the offered scope.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"The link, as the importer sees it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lotCount":{"type":"integer","minimum":0},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","requestedAt","grantedAt","acceptedAt","endedAt","lotCount","fields","shareDds","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No link names this workspace with that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"The link is not an open offer","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/importer/links/{id}/decline":{"post":{"tags":["Custody"],"summary":"Decline a producer’s offered supply link (as the importer)","description":"Ends the offer: it shares nothing and leaves the importer’s list.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplyLinkAnswer"}}}},"responses":{"200":{"description":"The link, as the importer sees it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["requested","offered","granted","declined","revoked"],"description":"`requested`: the importer asked; nothing is shared. `offered`: the producer offered a scope; nothing is shared until the importer accepts. `granted`: both sides agreed, the only state that shares anything. `declined` / `revoked`: ended for good; a new consent is a new link."},"producer":{"type":"object","properties":{"name":{"type":["string","null"]},"slug":{"type":"string"},"country":{"type":["string","null"]}},"required":["name","slug","country"],"additionalProperties":false},"requestedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"grantedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"acceptedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"endedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"lotCount":{"type":"integer","minimum":0},"fields":{"type":"array","items":{"type":"string"}},"shareDds":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","producer","requestedAt","grantedAt","acceptedAt","endedAt","lotCount","fields","shareDds","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No link names this workspace with that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"409":{"description":"The link is not an open offer","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/SupplyLinkProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/importer/links":{"get":{"tags":["Custody"],"summary":"The supply links naming this workspace as importer","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of links, in `(updatedAt, id)` order; an ended one says nothing of what it once shared","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterSupplyLinkList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/importer/lots":{"get":{"tags":["Custody"],"summary":"The lots producers shared with this workspace, as an importer may see them","description":"Resolves the granted links first: none, and the list is empty. Each lot is projected for the `importer` audience under its visibility policy narrowed to the fields the link names; a withheld key is absent, never blank.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The importer console is behind its preview gate (CUS-304) and cross-tenant: each lot is re-projected under the producer’s current consent on every read, so a revocation bites at once. It keeps `take`/`skip` until the console is released; an incremental feed of another company’s lots is a release decision, not a paging detail.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"linkId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"take","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"skip","in":"query"}],"responses":{"200":{"description":"The shared lots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterSharedLotList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/contaminations":{"post":{"tags":["Custody"],"summary":"Flag a plot or a certificate as contaminated","description":"Records that a plot or a certificate was found bad, and marks as affected everything that came from it: the lots harvested on the plot (or certified), every lot made from them through transformations or lineage links, the transformations, the shipments carrying them, and every DDS on any of those. The walk is bounded (`traceDepthLimit` steps); `truncated` says it reached a bound. Flagging the same source for the same reason while its flag is open does not flag it twice: it traces again, marks only what is new, and answers 200 with `replayed: true`.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationFlag"}}}},"responses":{"200":{"description":"Already flagged for this reason: traced again","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationTraceResult"}}}},"201":{"description":"Flagged","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationTraceResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such plot or certificate","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Refused: a reason that does not fit the source, a missing note, a certificate on something that cannot be traced","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List contamination flags","description":"Flags newest first, each with how many subjects it marked by type. `status=open` keeps the ones still in force. Pass the previous page's `nextCursor` as `cursor` to continue; a cursor this API did not produce is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["open","lifted"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of flags","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/contaminations/{id}":{"get":{"tags":["Custody"],"summary":"Read a contamination flag and what it marked","description":"The flag with its marks, nearest the source first (the first 500; `affectedTruncated` says there are more).","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The flag","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationDetail"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such flag","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/contaminations/{id}/retrace":{"post":{"tags":["Custody"],"summary":"Trace an open flag again","description":"Walks again from the flagged source and marks what came from it since (a lot made later, a DDS issued since). Nothing new: nothing is written. A lifted flag answers 409.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"Traced","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationTraceResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such flag","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"409":{"description":"The flag was lifted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/contaminations/{id}/lift":{"post":{"tags":["Custody"],"summary":"Lift a contamination flag","description":"Closes the flag with the reason (the source was cleared). The marks stay as history; they stop showing as affected. A flag is lifted once: a source found bad again is flagged again.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationLift"}}}},"responses":{"200":{"description":"Lifted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContamination"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such flag","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"409":{"description":"Already lifted","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"422":{"description":"The reason is missing","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/contaminations/{id}/mitigations":{"post":{"tags":["Custody"],"summary":"Record a mitigation so a DDS can be issued over an open flag","description":"A DDS whose subject (lot, shipment or plot) is reached by an open contamination flag is refused with `DDS_CONTAMINATION_OPEN` (EUDR Art. 10 and Art. 11). This records what was done about the flag for that subject (at least 20 characters) and from then on the flag no longer blocks that subject’s statement. The flag stays open and the banner stays. One note per flag and subject; the audit trail records its fingerprint, never its words. A flag that does not reach the subject answers 422 `MITIGATION_NOT_REACHING`.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationMitigate"}}}},"responses":{"201":{"description":"Recorded","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationMitigation"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such flag or subject","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"409":{"description":"The flag was lifted, or this subject already has a note on it","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"422":{"description":"The note is too short or too long, or the flag does not reach the subject","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List the mitigations recorded on a flag","description":"Every note recorded against the flag, oldest first.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A note is never edited: this keeps the notes recorded since."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A note is never edited: this keeps the notes recorded since.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of notes, oldest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationMitigationList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such flag","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyContaminationProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/passages":{"get":{"tags":["Custody"],"summary":"The passages a fixed gate reader saw of this lot","description":"CUS-308. Newest first: when and at which site’s gate the lot went through, which way, with which vehicle, as the gate reader behind the site’s hardware bridge saw it and the tag registry identified it.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A passage is never edited: this keeps the passages recorded since."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A passage is never edited: this keeps the passages recorded since.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of passages, newest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGatePassageList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not read field capture","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/vehicles/{id}/passages":{"get":{"tags":["Custody"],"summary":"The passages a fixed gate reader saw of this vehicle","description":"CUS-308. Newest first: when and at which site’s gate the vehicle went through, which way, and the lots identified with it.","x-origonex-scope":"master.read","security":[{"bearerAuth":["master.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A passage is never edited: this keeps the passages recorded since."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A passage is never edited: this keeps the passages recorded since.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of passages, newest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGatePassageList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not read field capture","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/bridge/events":{"post":{"tags":["Custody"],"summary":"Push signed events from a hardware bridge","description":"Up to 100 signed events of this workspace’s bridges, each answered on its own, in the order sent. A bridge is registered at a site from the web (settings → hardware), which shows its HMAC key once.\n\nAn event is the envelope `{bridgeId, deviceClass, sourceId, occurredAt, payload, signature}`; `signature` is the HMAC-SHA256, base64, of the canonical JSON of the other five fields with keys sorted at every level. Only `weighing_scale` is taken today.\n\nA `gate_reader` event (CUS-308) is ONE passage at the gate of the bridge’s site: `payload.reads` holds everything the fixed QR/RFID reader saw, each resolved in this workspace’s tag registry (a lot’s tag, a unit’s mark, a vehicle’s QR). It is answered with `passageId` (the passage recorded on the lots and the vehicle, the same one on a replay) or `passageId: null` with `passageOutcome` `no_match` (nothing of this workspace was identified; the reading is kept) or `vehicles_ambiguous` (two vehicles in one passage). Wire format: `spec/06_architecture/09_hardware-bridge.md` §\"Gate reader (CUS-308)\".\n\n`accepted: true` gives the reading’s `readingId` (what a receipt names in `weighing.readingId` or a line’s `readingId` (`POST /v1/custody/receipts`)) with `duplicate: true` when the same `(bridgeId, sourceId, occurredAt)` was accepted before (the first id comes back, nothing is written) and `usable: false` when the scale’s reading is not a weight (unstable, overload, underload, invalid): it is kept, and a receipt cannot take it.\n\n`accepted: false` gives the reason: `stale` (occurredAt more than 5 minutes from the server’s clock), `bad_signature`, `wrong_key`, `bridge_unknown` (including another workspace’s bridge), `bridge_revoked`, `plan_not_entitled` (the plan does not include the hardware bridge), `unsupported_device_class` (also a class the bridge was not registered for: Settings → Hardware), `malformed_envelope`, `malformed_payload`.","x-origonex-scope":"bridge.write","security":[{"bearerAuth":["bridge.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeEvents"}}}},"responses":{"200":{"description":"What became of each event","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeEventsResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Bridge keys cannot be read on this deployment (no key-encryption key); or temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":false,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyBridgeProblem"}}}}}}},"/custody/device-keys":{"get":{"tags":["Custody"],"summary":"List phone signing keys","description":"The phones’ signing keys, newest first, revoked ones included. `scope=mine` (default) lists the caller’s; `scope=workspace` lists every key and needs workspace settings. Only the public half of a key is ever here; the private half never leaves the phone’s keystore.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["mine","workspace"],"description":"`mine` (default): the caller’s keys. `workspace`: every key; needs workspace settings"},"required":false,"description":"`mine` (default): the caller’s keys. `workspace`: every key; needs workspace settings","name":"scope","in":"query"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A key changes once, when it is revoked."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. A key changes once, when it is revoked.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of keys, in `(updatedAt, id)` order","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not read these keys","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Register a phone signing key","description":"Registers the public half of an ECDSA P-256 key the phone generated in its keystore, bound to the CALLER and this workspace. `id` is a UUID the phone chose when it generated the key, so events it signed offline already name it. Recorded in the audit trail as `device_key.registered` (the id and the fingerprint).\n\nSafe to retry: the same id with the same key answers the key registered before (`replayed: true`, 200). Refused (422): a key that is not P-256 (`DEVICE_KEY_INVALID`), an id that names another key (`DEVICE_KEY_ID_TAKEN`), a key already registered under another id (`DEVICE_KEY_ALREADY_REGISTERED`), or a user holding 10 active keys (`DEVICE_KEY_LIMIT`).","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyRegistration"}}}},"responses":{"200":{"description":"The same key was registered before under this id: nothing was written","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyRegistered"}}}},"201":{"description":"The key, registered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyRegistered"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The key was refused","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/device-keys/{id}/revocation":{"post":{"tags":["Custody"],"summary":"Revoke a phone signing key","description":"Revokes a key, finally: from then on an event it signed is recorded with the verdict `revoked_key`, whatever time the phone claims it signed at; the events it signed before keep theirs. The caller may revoke a key of their own; any key needs workspace settings (a lost phone). Another member’s key answers 404 to anyone else. Recorded in the audit trail as `device_key.revoked`. Revoking a revoked key answers it as it is.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"The key, revoked","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKey"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not capture in the field","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"404":{"description":"No such key the caller may revoke","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyDeviceKeyProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/critical-link":{"get":{"tags":["Custody"],"summary":"Check the critical link of a lot's commodity","description":"Walks the lot’s upstream chain (both the transformations that made each lot and the recorded lot links; at most 5 000 lots and 64 links) and judges the one link where its commodity typically takes in material of unknown origin: the sawmill yield for wood, the indirect supplier (rearing and calf farms) for cattle, who each bunch load came from at the mill for palm oil, the village buyer for cocoa, the collector and the reseller for rubber, the point where coffee stops being one producer’s, and the silo (with mass balance) for soy. `status` is `pass`, `warn` (it fails or cannot be proven; `findings` say where, naming the lot) or `not_applicable` (the lot has not reached the link, or its commodity has no stage template). A warning does not refuse a statement; it is shown before one is issued. A chain that records no stage, a walk cut short, or a parent lot this workspace cannot see are warnings, never a pass.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One lot’s critical-link judgement, bounded (`truncated` says when).","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The check","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCriticalLinkResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCriticalLinkProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/certificates":{"get":{"tags":["Custody"],"summary":"The certificates a lot's chain of custody met","description":"Walks the lot’s upstream chain and lists every certificate it met (the lot’s own, the producer’s, an origin plot’s, the stage (transformation) that made a lot, the site it happened at or the site that received the lot, and the parties that own or run them), each judged at the moment the material passed there: `in_force`, `expired`, `not_yet_valid` or `suspended`. `inherited` says whether the lot carries that certification through a segregated chain. A certificate not in force is what the `chain.certificates_valid` check reports before a statement is issued.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One lot’s certificates as judged along its chain, computed on read; the certificate records themselves page at `GET /custody/certificates`.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The certificates","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyChainCertificates"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyChainCertificatesProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/claims":{"get":{"tags":["Custody"],"summary":"A lot’s certification claims","description":"The lot’s current claim under each scheme (`declared` (what the supplier’s invoice states, for a lot bought in) or `computed` (from the inputs of the step that made it, under the control system the step was run under)) and every declaration of the lot, oldest first, corrections included. `declarable` is false for a lot a step made: its claim is computed, never declared.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One lot’s claim summary, computed on read; the declarations themselves page at `GET /custody/claims`.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The claims","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLotClaims"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Record what a supplier’s invoice states about a lot","description":"Declares the lot’s claim under one scheme (FSC 100%, FSC Mix 70%, RSPO Segregated…) as its supplier’s invoice states it, with the supplier’s certificate code. To correct it, send `supersedesId` naming the lot’s current declaration for the scheme; a claim a step has already used cannot be corrected. A lot a step made cannot be declared (409). Send an `id` to make a retry safe: the same id with the same claim, certificate code, certificate and note returns the stored declaration with 200; the same id with any of them changed is a 409 (`CLAIM_ID_TAKEN`); send a correction under a new id.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyClaimDeclare"}}}},"responses":{"200":{"description":"Already declared with this id (a retry)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyClaimDeclaration"}}}},"201":{"description":"Declared","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyClaimDeclaration"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"409":{"description":"The lot’s claim is not the company’s to declare now (made by a step, declared already, superseded, used), or the id names another declaration","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"422":{"description":"A malformed claim, or a certificate that is not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/credit-accounts":{"get":{"tags":["Custody"],"summary":"The credit accounts and their balances","description":"One account per scheme × product class × site, kept by the credit systems (FSC/PEFC credit, mass balance): what came in, what went out, and the balance, which never goes negative. `siteId` and `scheme` narrow the list.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"siteId","in":"query"},{"schema":{"type":"string","enum":["fsc","pefc","rspo","rainforest_alliance","fairtrade","rtrs","proterra","four_c"]},"required":false,"name":"scheme","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of accounts, in `(updatedAt, id)` order","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCreditAccountList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/credit-accounts/{id}/entries":{"get":{"tags":["Custody"],"summary":"An account’s movements, newest first","description":"Each credit a step booked and each debit an output drew, with the step and the lot. Pass the previous page's `nextCursor` as `cursor` to continue; a cursor that was not produced by this API is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of entries","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCreditEntryList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such account","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyClaimProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/trademark-licences":{"get":{"tags":["Custody"],"summary":"The company's trademark licence codes","description":"Every licence code the company registered, one live per certification scheme, revoked ones kept with the date. A certification claim is shown on the public page only under a scheme with a live licence, with its code.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"A handful per workspace: one live licence per certification scheme, the revoked ones kept with their date.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"The licences","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role cannot read settings","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Register a scheme's trademark licence code","description":"Registers the code for the scheme, replacing (revoking) the live one. FSC codes are `FSC-C` and six digits, PEFC `PEFC/nn-nn-n…`, RSPO like `9-2497-18-100-00`; the other schemes take the code as printed. A malformed code is 422 `LICENCE_CODE_INVALID`.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceRegisterBody"}}}},"responses":{"201":{"description":"Registered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicence"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role cannot manage settings","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"LICENCE_CODE_INVALID","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/trademark-licences/{id}/revoke":{"post":{"tags":["Custody"],"summary":"Revoke a trademark licence code","description":"Ends the licence: a public claim under its scheme stops being shown on the next read. A revoked licence is 409.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"Revoked","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicence"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role cannot manage settings","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"404":{"description":"No such licence","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"409":{"description":"Already revoked","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyTrademarkLicenceProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/conflicts/{id}":{"get":{"tags":["Custody"],"summary":"Read an offline conflict between devices","description":"The item a conflict raised on a lot (drawn on beyond what it holds by records two devices made with no signal) or on a truck (received twice): every record it names (kept, flagged or refused) with who recorded it, how much, when on the ground and when it reached the server, and how the item was closed, if it was.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The item","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyConflict"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such item","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyConflictProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/conflicts/{id}/resolve":{"post":{"tags":["Custody"],"summary":"Close an offline conflict, explained","description":"Closes an open item with the approver's note: the surplus is real, or which side is wrong and how it is being put right. The note stays on the item; the audit trail records its fingerprint. While a lot's item is open, a DDS whose chain holds the lot is refused. An item already closed answers 404.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyConflictResolve"}}}},"responses":{"200":{"description":"Closed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyConflict"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No open item with this id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyConflictProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/visibility":{"get":{"tags":["Custody"],"summary":"Read the company’s visibility policy","description":"The policy in force for the company’s lots, field by field, with the catalogue default it starts from and where each answer comes from (`legacy` is one of the public verifier’s three switches, until the company saves a policy). A field names who may see it among `public` (anyone scanning a printed code), `buyer` (a customer holding a share link) and `importer` (a connected importer); `auditor` and `owner` always see everything that exists. Operator, plate, driver and exact coordinates are never public by default.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"The workspace’s one default visibility policy.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"The policy","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityView"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Change the company’s visibility policy","description":"Sets the audiences of each field named; `null` gives a field back to the catalogue default. Fields not named keep what they had: a company that never saved a policy starts from what its verifier switches already publish, so a first change never opens anything else. The verifier switches follow the policy. Every change is recorded in the audit trail with each field before and after. A field names who may see it among `public` (anyone scanning a printed code), `buyer` (a customer holding a share link) and `importer` (a connected importer); `auditor` and `owner` always see everything that exists. Operator, plate, driver and exact coordinates are never public by default.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityPatch"}}}},"responses":{"200":{"description":"The policy after the change","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityView"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"A widening change the plan does not include","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"404":{"description":"A widening change with the chain-of-custody programme off","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"409":{"description":"The policy changed at the same time; retry","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"422":{"description":"CLAIM_LICENCE_REQUIRED: the certification claim cannot be opened to the public without a trademark licence code for its scheme (CUS-612)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/visibility":{"get":{"tags":["Custody"],"summary":"Read a lot’s visibility policy","description":"The policy in force for one lot: its exception, where it has one, over the company’s policy. A field names who may see it among `public` (anyone scanning a printed code), `buyer` (a customer holding a share link) and `importer` (a connected importer); `auditor` and `owner` always see everything that exists. Operator, plate, driver and exact coordinates are never public by default.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One lot’s visibility policy.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The policy","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityView"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custody"],"summary":"Change a lot’s visibility exception","description":"Sets, for this lot only, the audiences of each field named; `null` gives a field back to the company’s policy. A change that leaves nothing different from the company’s policy removes the exception. A field names who may see it among `public` (anyone scanning a printed code), `buyer` (a customer holding a share link) and `importer` (a connected importer); `auditor` and `owner` always see everything that exists. Operator, plate, driver and exact coordinates are never public by default.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityPatch"}}}},"responses":{"200":{"description":"The lot’s policy after the change","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityView"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"A widening change the plan does not include","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"404":{"description":"No such lot, or a widening change with the programme off","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"409":{"description":"The exception changed at the same time; retry","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"422":{"description":"CLAIM_LICENCE_REQUIRED: the lot's certification claim cannot be opened to the public without a trademark licence code for each of its schemes (CUS-612)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Custody"],"summary":"Remove a lot’s visibility exception","description":"The lot follows the company’s policy again. Accepted on every plan and with the chain-of-custody programme off: it is how a company takes a lot back to its default after a downgrade.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The lot’s policy after the change","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityView"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/visibility/preview":{"get":{"tags":["Custody"],"summary":"Preview a lot as each audience receives it","description":"The lot’s record (origin, stages, events, transports, receipts, transformations, documents, certificates, seal) through the same projection every read that leaves the company goes through, once per audience (or for `audience` only). A key the audience may not see is absent, not blanked; a section closed to it is absent entirely.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"What each audience sees of one lot.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","enum":["public","buyer","importer","auditor","owner"],"description":"`public`: anyone scanning a printed code. `buyer`: a customer holding a share link. `importer`: a connected importer acting with consent. `auditor`: an engagement holder. `owner`: the company itself. `auditor` and `owner` always see everything that exists."},"required":false,"description":"`public`: anyone scanning a printed code. `buyer`: a customer holding a share link. `importer`: a connected importer acting with consent. `auditor`: an engagement holder. `owner`: the company itself. `auditor` and `owner` always see everything that exists.","name":"audience","in":"query"}],"responses":{"200":{"description":"The lot per audience","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityPreview"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyVisibilityProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/certificates/{id}/registry-check":{"post":{"tags":["Custody"],"summary":"Check a certificate in its certifier's registry","description":"Asks the certification scheme's public registry (FSC, RSPO) about this certificate now, stores the answer on the certificate (status, when, and where it was read) and records it in the audit trail. A registry answering anything but `valid` becomes a warning in the certificate checks. When the registry cannot be read nothing is written: 502, or 429 when the registry asks to slow down. `detail` carries the machine code: CERTIFICATE_NOT_FOUND, SCHEME_NOT_SUPPORTED, REGISTRY_OFF, REGISTRY_NOT_CONFIGURED, REGISTRY_UNAVAILABLE, CHECKED_RECENTLY (one check per certificate per minute), REGISTRY_BUSY (the registry's own call quota, FSC 5 a minute, shared with the nightly re-checks, has no call left; nothing was asked), FSC_LICENCE_CODE_REQUIRED (an FSC certificate recorded by a code other than its licence code FSC-C######; nothing was asked). A `holderName` in the body is compared and shown, and recorded as typed: it never marks the certificate verified; only the certificate's own subject party can.","x-origonex-scope":"master.write","security":[{"bearerAuth":["master.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryCheckBody"}}}},"responses":{"200":{"description":"Checked","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryCheck"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such certificate","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryProblem"}}}},"409":{"description":"The check is off or not configured here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryProblem"}}}},"422":{"description":"No registry check for this scheme, or an FSC certificate not recorded by its licence code","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryProblem"}}}},"429":{"description":"The registry asked to slow down, its call quota has no call left (REGISTRY_BUSY), or this certificate was checked less than a minute ago","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryProblem"}}}},"502":{"description":"The registry could not be read","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CertificateRegistryProblem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/cooperatives":{"get":{"tags":["Custody"],"summary":"List the workspace's cooperatives","description":"The workspace itself when it is a cooperative (the Cooperative Plan, one of its own sites is a cooperative, or it has members; id `workspace`), then the parties that own a cooperative site or have members, each with its live sites and the members whose membership is open now.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"One summary per cooperative (its sites and open memberships, counted on read), a handful per workspace. The records behind it sync through `GET /parties`, `GET /custody/sites` and `GET /custody/cooperatives/{id}/members`.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"The cooperatives","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/cooperatives/candidates":{"get":{"tags":["Custody"],"summary":"Parties that could become a cooperative","description":"Live parties of a kind that can have members (not a carrier, a certifier or a family farmer) that are not a cooperative yet (no cooperative site, no members) in name order, a page at a time; `workspace` says whether this workspace itself is not listed as one yet. A party becomes a cooperative when it gets its first member.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"A type-ahead search (`q`) with its own cursor; it reads names, not a history, so there is nothing to sync incrementally.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","maxLength":120},"required":false,"name":"q","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A page of candidates","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeCandidates"}}}},"400":{"description":"A cursor this server did not issue","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/cooperatives/{id}/totals":{"get":{"tags":["Custody"],"summary":"A cooperative's consolidated totals over a period","description":"`{id}` is a party, or `workspace` for this workspace itself. Members (at the end of the period, joined and left in it), their plots, what the cooperative received in `[from, to)` (its own transfers between its sites are not received again): per unit, per member and per month, in the lot’s stored unit (kg for a mass), and, now, the lots holding a balance at its sites and the open receipt-divergence and conflict items on its trips and lots. Every number is one aggregate over the records themselves.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"Aggregates of one cooperative over a period.","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","format":"date-time","description":"Start of the period, inclusive. Omitted: since the first record."},"required":false,"description":"Start of the period, inclusive. Omitted: since the first record.","name":"from","in":"query"},{"schema":{"type":"string","format":"date-time","description":"End of the period, exclusive. Omitted: now."},"required":false,"description":"End of the period, exclusive. Omitted: now.","name":"to","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":64,"description":"IANA time zone the months of `received.byMonth` are cut in. Omitted: the workspace’s time zone, or UTC."},"required":false,"description":"IANA time zone the months of `received.byMonth` are cut in. Omitted: the workspace’s time zone, or UTC.","name":"timeZone","in":"query"}],"responses":{"200":{"description":"The totals","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeTotals"}}}},"400":{"description":"An empty or inverted period","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such cooperative","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/cooperatives/{id}/members":{"get":{"tags":["Custody"],"summary":"A cooperative's members","description":"A page of members in name order, each with its membership period and live plots. `scope=all` adds former members.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","enum":["active","all"],"description":"`active` (default): open memberships. `all`: former members too."},"required":false,"description":"`active` (default): open memberships. `all`: former members too.","name":"scope","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"}],"responses":{"200":{"description":"A page of members","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeMemberPage"}}}},"400":{"description":"A cursor this server did not issue","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such cooperative","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custody"],"summary":"Add a member to a cooperative","description":"Opens a membership from `joinedAt` (default now; never in the future). The member must be a producer of the workspace (supplier, sub-supplier, processor, smallholder) that has not withdrawn its consent to be traced; a pair has at most one open membership, and a rejoin starts on or after the last leave.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeMemberAdd"}}}},"responses":{"201":{"description":"Added","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeMembership"}}}},"400":{"description":"Not a producer, or a date refused","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such cooperative","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"409":{"description":"Already a member, or overlapping a past membership","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/cooperatives/{id}/members/{membershipId}/end":{"post":{"tags":["Custody"],"summary":"End a member's membership","description":"Closes an open membership at `leftAt` (default now; never in the future, never before joining). Deliveries received while it was open stay the member’s.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"membershipId","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeMemberEnd"}}}},"responses":{"200":{"description":"Ended","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeMembership"}}}},"400":{"description":"A date refused","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such membership","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"409":{"description":"Already ended","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyCooperativeProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/lacey-summary":{"post":{"tags":["Custody"],"summary":"Generate a lot's Lacey Act declaration summary for the customs broker","description":"Builds the PPQ 505 lines the chain of custody answers (genus and species from the lots, country of harvest from the production plots those lots came from, the quantity when the chain can state it, the origin lots) and returns them with the file (`pdf` or `csv`, base64). Species and country are paired by origin lot, never crossed. Fields that belong to the importer of record (entry number, port, EIN, entered value, percent recycled, the due-care statement) are left blank for the broker, who files the declaration. `gaps` names what the chain could not answer. Species and country are never paired where the chain did not pair them: an origin lot with several species and several countries lists its countries as `unpairedCountries` with the gap `species_country_pairing_ambiguous`. Each generation is recorded in the audit trail with the SHA-256 of the file. PPQ 505 is required for wood only: any other commodity is refused with 422 and the reason in `detail` (`LACEY_NOT_A_PLANT_PRODUCT` cattle, `LACEY_OUT_OF_SCOPE_FOOD_CROP` soy, `LACEY_EXEMPT_COMMON_CULTIVAR` palm oil, `LACEY_NO_CURRENT_OBLIGATION` cocoa, coffee and rubber).","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLaceySummaryRequest"}}}},"responses":{"200":{"description":"The summary and its file","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyLaceySummary"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyOutputProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"No US Lacey declaration applies to the lot’s commodity","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyOutputProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/buyer-pack":{"post":{"tags":["Custody"],"summary":"Generate a lot's buyer audit pack","description":"Builds the lot’s chain of custody (the lot and every lot upstream of it, with their stages, trips, receipts and the transformations that made them), its documents and its certificates, as the `buyer` audience may see them under the company’s visibility policy: a field or section the policy closes to buyers is absent, and a natural person’s name never appears. Returns a PDF, printed in `locale` (the seven launch languages; English when omitted), and a JSON manifest listing the SHA-256 of the PDF and of each shared document, both base64, with `sections` telling the company what the pack carries. Each generation is recorded in the audit trail with both hashes.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","es","fr","de","it","ja"]},"required":false,"name":"locale","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"200":{"description":"The pack and its manifest","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyBuyerPack"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyOutputProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/units":{"post":{"tags":["Custody"],"summary":"Generate serialised units under a lot","description":"Makes `count` units (1 to 10 000) under the lot (a door, a sack, a box, a bale each) with a serial that is the GS1 AI (21) value printed on the piece: `random` (12 characters of Crockford base32 from a cryptographic source, after an optional prefix of up to 8 characters) or `sequential` (the prefix and a zero-padded number, going on from the last number used under that prefix). With a `gtin`, each unit also gets a GS1 Digital Link, and a serial is unique across every lot of that GTIN; without, unique within the lot.\n\nA lot counted in pieces holds no more units than it has pieces. Each unit has its own public page, opened by a key that is never the serial (listed by `GET …/units`). Once a lot has units, its quantity, unit and commodity are fixed and it cannot be deleted.\n\nIdempotent by `requestId`: the same request again answers `replayed` with what the first made; the same id with a different request is refused with 409.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyUnitGenerateBody"}}}},"responses":{"200":{"description":"The units were made, or had been made by this request id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyUnitGeneration"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The plan does not include unit pages","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"409":{"description":"The request id was used for a different request, or a serial was taken","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"422":{"description":"The request cannot be made: a prefix, a GTIN or a serial length GS1 does not allow, or more units than the lot holds","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List a lot's units","description":"The lot's units in the order they were made (then by serial), a page at a time, with the total. Each carries its public page (`pageUrl`) and, with a GTIN, its GS1 Digital Link; both open the unit's page, so treat them like the printed mark.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","maxLength":256,"description":"The `nextCursor` of the previous page."},"required":false,"description":"The `nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Units per page, 1 to 200 (default 50)."},"required":false,"description":"Units per page, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"}],"responses":{"200":{"description":"A page of units","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyUnitPage"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/units":{"get":{"tags":["Custody"],"summary":"List every unit of the workspace","description":"Every unit of the workspace's live lots, in `(updatedAt, id)` order (a unit's `updatedAt` moves when its status does) with its lot. The feed an ERP syncs from with `updatedSince`; a lot's own units, in the order they were made, are at `GET /custody/batches/{id}/units`.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of units","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyUnitRecordPage"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/units/{id}":{"get":{"tags":["Custody"],"summary":"Read one unit","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The unit","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyUnitRecord"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No unit of a live lot of this workspace has that id","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyUnitProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/auditor-opinions":{"get":{"tags":["Custody"],"summary":"The auditors’ opinions on a lot, every version","description":"Every opinion an auditor signed on the lot under an engagement, newest first, including the ones replaced, each marked `replaced` with the opinion that replaced it; a replacement carries the reason. An opinion is never edited or deleted. Each one carries its fingerprint (sha256 over its fields), the platform’s detached signature over that fingerprint, and `integrity`: whether the fingerprint recomputed from the opinion as stored now still matches, whether the audit trail attests the same fingerprint, and whether the signature verifies. At most 200 versions; `truncated` says when there are more.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","enum":["v2"],"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`."},"required":false,"description":"`v2`: answer `{ data, pageInfo }` only, the shape of every newer list. Omitted: the shape this list answered before (kept for its clients), plus `pageInfo`.","name":"shape","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400,"description":"The `pageInfo.nextCursor` of the previous page."},"required":false,"description":"The `pageInfo.nextCursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1 to 200 (default 50)."},"required":false,"description":"Page size, 1 to 200 (default 50).","name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. An opinion is never edited: a replacement is a new version, and it is listed."},"required":false,"description":"Incremental sync: only what was written or changed at or after this instant, read from a 5-minute overlap before it because writes commit out of timestamp order; dedupe by id. An opinion is never edited: a replacement is a new version, and it is listed.","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of opinions, newest first","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyAuditorOpinionList"}}}},"400":{"description":"The cursor is not one this API issued (`invalid_query_param`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CursorProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyAuditorOpinionProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/gov-documents/support":{"get":{"tags":["Custody"],"summary":"Whether a government document can be fetched by its number here","description":"The kinds (`dof`, `gf`, `gta`) this deployment can fetch from the registry by number. Off by default: the registries need credentials the workspace holds, and without them a document is imported from its export.","x-origonex-scope":"custody.read","x-origonex-unpaginated":"Which document kinds this deployment can fetch.","security":[{"bearerAuth":["custody.read"]}],"responses":{"200":{"description":"The lookup","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentSupport"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/gov-documents":{"post":{"tags":["Custody"],"summary":"Import a government transport document","description":"A DOF or GF (Sinaflor / SISFLORA) or a GTA (GTA-e), sent as the exported file’s bytes (`contentBase64`: decoded by the XML prolog’s declared encoding, UTF-8 or ISO-8859-1, and hashed as exported), as text already decoded (`content`: pasted XML, or JSON in the normalised shape; text carrying U+FFFD is refused as mis-decoded) or, where the lookup is on, fetched by `lookup` (kind, number, issuing state). The answer carries what was read, what the workspace’s records propose for it (the vehicle by plate, the places, a lot per species) and, when it matches a transport already recorded, the fields that differ. Idempotent by the document’s identity (kind, state, series, number): a second import answers 200 with `replayed: true` and the first row untouched; `contentChanged` says the bytes differ. When the registry cannot be read nothing is written: 502.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentImport"}}}},"responses":{"200":{"description":"Imported before (a replay)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentImportResult"}}}},"201":{"description":"Imported","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentImportResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"The registry holds no such document","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"409":{"description":"The step does not fit the document or the transport as they stand (a load that cannot be “fixed”, a lot that does not hold that much), or the lookup by number is off on this deployment","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"422":{"description":"Refused: the body failed the schema (`errors` names the fields), the export is unreadable, too large (GOV_DOCUMENT_TOO_LARGE) or mis-encoded (GOV_DOCUMENT_ENCODING_INVALID), not a DOF / GF / GTA, a difference left undecided, or a reference that is not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"The registry could not be read","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Custody"],"summary":"List imported government documents","description":"Imported documents in (updatedAt, id) order, without their check (read one with GET …/{id}). `order=asc` (the default, a sync's order: oldest change first) or `order=desc` (newest first, what a person scrolling wants); a cursor continues only the order that produced it. `status=pending` is what still waits for a decision; `transportId` keeps the documents linked to a transport. Pass the previous page's `nextCursor` as `cursor` to continue; a cursor this API did not produce is refused with 400.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["pending","applied"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["asc","desc"]},"required":false,"name":"order","in":"query"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":false,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"transportId","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of documents","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentList"}}}},"400":{"description":"The cursor is malformed","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"A query parameter failed the schema (`errors` names it)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/gov-documents/{id}":{"get":{"tags":["Custody"],"summary":"Read a government document and its check","description":"The document as read, the proposal (vehicle, places, a lot per line) and, against the transport it is checked with, every difference: plate, origin, destination, species, quantity, unit, validity. While pending and checked against no transport, `candidates` lists the transports it could describe.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The document","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocument"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"No such document (or not this workspace’s)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/gov-documents/{id}/match":{"post":{"tags":["Custody"],"summary":"Check a pending document against another transport","description":"Points the pending document at one of the workspace’s transports (`transportId`) (the differences are computed against it) or at none (`null`), to create a transport from it instead.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentMatch"}}}},"responses":{"200":{"description":"The document, checked again","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocument"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"No such document (or not this workspace’s)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"409":{"description":"The step does not fit the document or the transport as they stand (a load that cannot be “fixed”, a lot that does not hold that much), or the lookup by number is off on this deployment","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"422":{"description":"Refused: the body failed the schema (`errors` names the fields), the export is unreadable, too large (GOV_DOCUMENT_TOO_LARGE) or mis-encoded (GOV_DOCUMENT_ENCODING_INVALID), not a DOF / GF / GTA, a difference left undecided, or a reference that is not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/gov-documents/{id}/confirm":{"post":{"tags":["Custody"],"summary":"Create the transport from the document, or decide every difference","description":"Checked against no transport: creates one through the transport engine: the document’s plate (or `vehicleId`; `registerVehicle: true` registers the plate, which needs the vehicle register’s write), its origin and destination, a load per line on the lot proposed or named in `items`, the route between the places. Checked against a transport: every difference needs a decision in `resolutions`: `accept` records it, `fix` brings a planned transport’s header to the document’s value; a load is never fixed. Idempotent: applied again answers `replayed: true` with nothing written.","x-origonex-scope":"custody.write","security":[{"bearerAuth":["custody.write"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentConfirm"}}}},"responses":{"200":{"description":"Applied, or already applied","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentConfirmResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not do this: reading needs field capture (read), every write field capture (write), and `registerVehicle` the vehicle register’s write; a field role reaches no path here","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"404":{"description":"No such document (or not this workspace’s)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"409":{"description":"The step does not fit the document or the transport as they stand (a load that cannot be “fixed”, a lot that does not hold that much), or the lookup by number is off on this deployment","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"422":{"description":"Refused: the body failed the schema (`errors` names the fields), the export is unreadable, too large (GOV_DOCUMENT_TOO_LARGE) or mis-encoded (GOV_DOCUMENT_ENCODING_INVALID), not a DOF / GF / GTA, a difference left undecided, or a reference that is not this workspace’s","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyGovDocumentProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/imports":{"post":{"tags":["Custody"],"summary":"Import records in bulk (CSV or JSON)","description":"Sites, vehicles, drivers, transports, receipts, transformations and units, and the origin base: parties (a CNPJ checked by its digits), plots (a polygon checked by PostGIS, or a point with its declared area) and lots naming them by `#key`, from CSV or JSON files. Answers 202 with the job; poll `GET /v1/custody/imports/{id}`. All or nothing: a job that ends `invalid` wrote NOTHING, and its `errors` list every problem by file, line and column in the asked language. The same upload sent again after it committed answers with that job (`replayed: true`) and writes nothing.","x-origonex-scope":"bulk.write","security":[{"bearerAuth":["bulk.write"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyImportCreate"}}}},"responses":{"200":{"description":"This upload was already committed: its job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyImportJob"}}}},"202":{"description":"Accepted; poll the job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyImportJob"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not import this kind of record","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"404":{"description":"Not found, or chain-of-custody is not enabled for this workspace (`not_found`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/imports/{id}":{"get":{"tags":["Custody"],"summary":"Read an import job","x-origonex-scope":"bulk.write","security":[{"bearerAuth":["bulk.write"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":2,"maxLength":16},"required":false,"name":"locale","in":"query"}],"responses":{"200":{"description":"The job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyImportJob"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/imports/{id}/commit":{"post":{"tags":["Custody"],"summary":"Commit a previewed import","description":"Writes a `ready` preview, all or nothing. Answers 202; poll the job. A job that is not `ready` is refused with 409.","x-origonex-scope":"bulk.write","security":[{"bearerAuth":["bulk.write"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":2,"maxLength":16},"required":false,"name":"locale","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"responses":{"202":{"description":"Accepted; poll the job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustodyImportJob"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not import this kind of record","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"404":{"description":"No such job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"409":{"description":"The job is not ready","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/imports/{id}/errors":{"get":{"tags":["Custody"],"summary":"Download an import’s error report (CSV)","x-origonex-scope":"bulk.write","x-origonex-unpaginated":"One import job’s error report, as a CSV file (line, column, code, message), bounded by the job’s own error cap, and a download, not a collection to sync.","security":[{"bearerAuth":["bulk.write"]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":2,"maxLength":16},"required":false,"name":"locale","in":"query"}],"responses":{"200":{"description":"file, line, column, code, message, in the asked language","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such job","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/exports/{entity}":{"get":{"tags":["Custody"],"summary":"Export one kind of record (CSV or JSON)","description":"Every live record of the kind, up to 10 000, as a file. Parties, plots, lots, sites, vehicles and drivers come in the import’s own shape (`key` is the id, and a reference between parties, plots and lots is `#<id>`), so an export imports back; plots also as GeoJSON or KML (`format=geojson|kml`). Drivers’ document numbers are whole from `master_data:approve` and masked below it. Units need `batchId`. Transports, receipts, transformations and sites carry their custom values for a caller holding `custom-fields.read` while custom fields are on: in CSV one `cf:<key>` column per field (a money field adds `cf:<key>:currency`; choices joined with `|`), in JSON a `customFields` object.","x-origonex-scope":"custody.read","security":[{"bearerAuth":["custody.read"]}],"parameters":[{"schema":{"type":"string","enum":["parties","plots","lots","sites","vehicles","drivers","transports","receipts","transformations","units"]},"required":true,"name":"entity","in":"path"},{"schema":{"type":"string","enum":["csv","json","geojson","kml"],"default":"csv","description":"`geojson` and `kml` are for `plots` only (400 otherwise)."},"required":false,"description":"`geojson` and `kml` are for `plots` only (400 otherwise).","name":"format","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Units only: the lot whose units to export (required for `units`)."},"required":false,"description":"Units only: the lot whose units to export (required for `units`).","name":"batchId","in":"query"}],"responses":{"200":{"description":"The file","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"application/geo+json":{"schema":{"type":"object","additionalProperties":{}}},"application/vnd.google-earth.kml+xml":{"schema":{"type":"string"}}}},"400":{"description":"Units without `batchId`, or GeoJSON/KML asked for anything but plots","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The role may not read this kind of record","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"404":{"description":"No such lot","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"422":{"description":"More than 10 000 records: use the paged list","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustodyImportProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields":{"get":{"tags":["Custom fields"],"summary":"List the workspace’s custom fields","description":"Every field of the workspace, or of one record kind, in its display order, with the current version flattened. Retired fields are included unless `status=active`. Read the whole catalogue: it is bounded by the plan.","x-origonex-scope":"custom-fields.read","x-origonex-unpaginated":"The workspace’s field catalogue, bounded by the plan (≤ 200 active) and the technical cap; a client reads it whole.","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme."},"required":false,"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme.","name":"recordKind","in":"query"},{"schema":{"type":"string","enum":["active","retired"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"The catalogue","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldList"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Custom fields"],"summary":"Create a custom field","description":"A new field, version 1, visible to the company only; open it with `PUT /custom-fields/{id}/visibility`. `key`, `type` and `recordKind` never change. Recorded in the audit trail as `custom_field.created`.","x-origonex-scope":"custom-fields.manage","security":[{"bearerAuth":["custom-fields.manage"]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldCreateBody"}}}},"responses":{"201":{"description":"The field","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not manage settings (`forbidden`), or the plan’s active-field limit is reached (`plan_limit_reached`, `PLAN_LIMIT_REACHED:maxCustomFields`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"404":{"description":"Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"409":{"description":"The key is already used for this record kind (`custom_field_key_taken`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"The definition does not parse (`custom_field_definition_invalid`), names a scope value the workspace does not have (`custom_field_scope_unknown`), or the record kind is full (`custom_field_kind_full`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields/{id}":{"get":{"tags":["Custom fields"],"summary":"Read a custom field","description":"One field with every version, oldest first.","x-origonex-scope":"custom-fields.read","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"responses":{"200":{"description":"The field, with every version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such field in this workspace (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custom fields"],"summary":"Revise a custom field","description":"A new version with the labels, help, requiredness, config or scope given (`custom_field.revised`). Values already stored keep the version they were captured under. A body that changes nothing answers the field as it is.","x-origonex-scope":"custom-fields.manage","security":[{"bearerAuth":["custom-fields.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldPatchBody"}}}},"responses":{"200":{"description":"The field, with every version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such field in this workspace (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"The revision does not fit the field’s type or record kind, or deletes a choice option (`custom_field_definition_invalid`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields/{id}/retire":{"post":{"tags":["Custom fields"],"summary":"Retire a custom field","description":"A new version, retired: the field leaves the forms; every value already stored stays and stays visible. Frees a plan slot. Retiring a retired field changes nothing.","x-origonex-scope":"custom-fields.manage","security":[{"bearerAuth":["custom-fields.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldStatusChangeBody"}}}},"responses":{"200":{"description":"The field, with every version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such field in this workspace (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields/{id}/restore":{"post":{"tags":["Custom fields"],"summary":"Restore a retired custom field","description":"A new version, active again. Counts against the plan’s active-field limit, as a create does.","x-origonex-scope":"custom-fields.manage","security":[{"bearerAuth":["custom-fields.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key."},"required":false,"description":"Makes a retry safe: a POST repeated with the same key and the same request answers the first result (`Idempotent-Replayed: true`) without running again; the same key with a different request is 409 `idempotency_conflict`; while the first is still running, 409 `idempotency_in_progress` with `Retry-After`. Keys live 24 hours and belong to the workspace and path, not to the API key: a request re-sent under a rotated key replays instead of writing twice. A replay is re-checked for the caller as they are now (scope and role). Only a 2xx answer is remembered: a refused request can be retried with the same key.","name":"Idempotency-Key","in":"header","example":"erp-order-4711-transport"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldStatusChangeBody"}}}},"responses":{"200":{"description":"The field, with every version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not manage settings, or the plan’s active-field limit is reached (`plan_limit_reached`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"404":{"description":"No such field in this workspace (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"409":{"description":"The Idempotency-Key was used with a different request (`idempotency_conflict`) or is still running (`idempotency_in_progress`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields/{id}/visibility":{"put":{"tags":["Custom fields"],"summary":"Set who sees a custom field","description":"Who sees the field besides the company (`auditor`, `importer`, `buyer`, `public`), and whether field roles fill it. Live: closing bites on the next read everywhere, including on values captured long ago. Adding an audience needs the Growth plan and custom fields on; removing one is allowed on every plan and with custom fields off. `public` is refused for money and text fields. Recorded as `custom_field.visibility_changed`.","x-origonex-scope":"sharing.manage","security":[{"bearerAuth":["sharing.manage"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldVisibilityBody"}}}},"responses":{"200":{"description":"The field, with every version","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomField"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not manage settings, or opening the field outside the company is not in the plan (`plan_feature_locked`, `PLAN_FEATURE_LOCKED:custodyFieldVisibility`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"404":{"description":"No such field in this workspace (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"`public` on a money field (`custom_field_money_not_public`) or a text field (`custom_field_text_not_public`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-fields/order":{"put":{"tags":["Custom fields"],"summary":"Order a record kind’s custom fields","description":"The fields listed first, in the order given, then any field of the kind not listed, in its current order (`custom_field.reordered`).","x-origonex-scope":"custom-fields.manage","security":[{"bearerAuth":["custom-fields.manage"]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldOrderBody"}}}},"responses":{"204":{"description":"Ordered","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"An id that is not a field of this kind (`not_found`), or Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-field-values":{"get":{"tags":["Custom fields"],"summary":"List and filter custom values","description":"The records of one kind with their current custom values, in `(updatedAt, recordId)` order: the feed an external system syncs from.\n\nName a `field` to keep only the records holding it, and filter on it with one of `eq`, `in` (comma-separated) or `isSet`, or a `gte` / `lte` range: numbers and money amounts as decimal strings, dates as `YYYY-MM-DD`, choices by key, yes/no as `true` / `false`; `currency` narrows a money field. A filter a type cannot take is 422 `custom_field_invalid`.","x-origonex-scope":"custom-fields.read","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record in a values path (every kind a field can sit on)."},"required":true,"description":"The kind of record in a values path (every kind a field can sit on).","name":"recordKind","in":"query"},{"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"required":false,"name":"field","in":"query"},{"schema":{"type":"string","maxLength":2000},"required":false,"name":"eq","in":"query"},{"schema":{"type":"string","maxLength":4000,"description":"Comma-separated values."},"required":false,"description":"Comma-separated values.","name":"in","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"gte","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"lte","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"isSet","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{3}$"},"required":false,"name":"currency","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of records","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldValuesList"}}}},"400":{"description":"The cursor is not one this API issued","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such field (`not_found`), or custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"An unknown field (`custom_field_unknown`), or a filter its type cannot take (`custom_field_invalid`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-field-values/export":{"get":{"tags":["Custom fields"],"summary":"Export one record kind’s custom values (CSV or JSON)","description":"One row per current value (`recordKind, recordId, key, type, value, unit, currency, fieldVersion, updatedAt`), retired fields included, cleared values left out. A money value is its amount, its currency in `currency`; choices are joined with `|` in CSV. Up to 10 000 rows; beyond, page them with `GET /custom-field-values`. Recorded in the audit trail as `custody_export.generated`.","x-origonex-scope":"custom-fields.read","x-origonex-unpaginated":"A download of one record kind’s current values (≤ 10 000 rows), not a collection to sync; `GET /custom-field-values` pages them.","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record in a values path (every kind a field can sit on)."},"required":true,"description":"The kind of record in a values path (every kind a field can sit on).","name":"recordKind","in":"query"},{"schema":{"type":"string","enum":["csv","json"],"default":"csv","description":"Default `csv`."},"required":false,"description":"Default `csv`.","name":"format","in":"query"}],"responses":{"200":{"description":"The file","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{}}}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"More than 10 000 values: use the paged list","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-field-values/{recordKind}/{recordId}":{"get":{"tags":["Custom fields"],"summary":"Read a record’s custom values","description":"The record’s current values, every field (retired ones included), labelled in `lang`, else the first `Accept-Language` tag this API speaks, else the workspace’s language. A cleared value is absent.","x-origonex-scope":"custom-fields.read","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record in a values path (every kind a field can sit on)."},"required":true,"description":"The kind of record in a values path (every kind a field can sit on).","name":"recordKind","in":"path"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"recordId","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","es","fr","de","it","ja"],"description":"The language of the labels; else the first `Accept-Language` tag this API speaks, else the workspace’s default."},"required":false,"description":"The language of the labels; else the first `Accept-Language` tag this API speaks, else the workspace’s default.","name":"lang","in":"query"}],"responses":{"200":{"description":"The values","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldRecordValues"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such record in this workspace (`not_found`), or custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Custom fields"],"summary":"Set or clear a record’s custom values","description":"Writes the values given (`null` clears), each judged against its field’s definition as of `customFieldsAsOf` and against the record as stored. Every write is kept: a change is a new value, and the history lists both. Recorded in the audit trail as `custom_field.values_set` (fingerprints only, never the value) and announced as the `custom_field.values_changed` webhook.\n\n`Idempotency-Key` is the request id: the same key again answers what the first write stored (`replayed: true`) and writes nothing. `basedOn` names the value you last saw; a mismatch is not refused: the write is kept and the field is flagged as changed on two devices. A required field cannot be cleared.","x-origonex-scope":"custom-fields.write","security":[{"bearerAuth":["custom-fields.write"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record in a values path (every kind a field can sit on)."},"required":true,"description":"The kind of record in a values path (every kind a field can sit on).","name":"recordKind","in":"path"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"recordId","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"The request id of this write: repeating it answers the stored result without writing again."},"required":false,"description":"The request id of this write: repeating it answers the stored result without writing again.","name":"Idempotency-Key","in":"header","example":"erp-costrun-2026-10-03-bat_door"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldValuesPatch"}}}},"responses":{"200":{"description":"The record’s values after the write","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldValuesWriteResult"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The caller may not write this kind of record (`forbidden`), or the API key lacks `custom-fields.write` (`scope_insufficient`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"404":{"description":"No such record in this workspace (`not_found`), or custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"409":{"description":"The Idempotency-Key was used on another record (`idempotency_conflict`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"A value refused: `custom_field_unknown`, `custom_field_retired`, `custom_field_not_applicable`, `custom_field_invalid` (`CUSTOM_FIELD_INVALID:<key>:<reason>`), `custom_field_required`, `custom_field_too_many_values`; `errors[].pointer` names the field","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custom-field-values/{recordKind}/{recordId}/history":{"get":{"tags":["Custom fields"],"summary":"The history of a record’s custom values","description":"Every write of the record’s values, newest first: who, when (the device’s time and the server’s), under which version of the field, and whether it was cleared, written over another device’s value, or erased at the data subject’s request. `updatedSince` keeps the writes recorded since (5-minute overlap).","x-origonex-scope":"custom-fields.read","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record in a values path (every kind a field can sit on)."},"required":true,"description":"The kind of record in a values path (every kind a field can sit on).","name":"recordKind","in":"path"},{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"recordId","in":"path"},{"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$","description":"Only this field’s writes."},"required":false,"description":"Only this field’s writes.","name":"field","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":400},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"required":false,"description":"ISO 8601 timestamp with timezone offset","name":"updatedSince","in":"query"}],"responses":{"200":{"description":"A page of the history","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueHistory"}}}},"400":{"description":"The cursor is not one this API issued","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks the scope (`scope_insufficient`), or the caller’s role lacks the capability (`forbidden`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such record in this workspace (`not_found`), or custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"An unknown field (`custom_field_unknown`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/custody/batches/{id}/custom-fields/upstream":{"get":{"tags":["Custom fields"],"summary":"Everything upstream of a lot, with its custom values","description":"The cost-per-door helper: the lot and every lot upstream of it (by parent links and transformations, the walk the chain verification makes), and the transports, receipts and transformations that touched them, each with the company’s custom values, quantities and units. Lots deepest first, then trips, receipts and transformations in the order they were recorded. At most 2 000 nodes; `truncated` says when the walk was cut.\n\nOrigonex computes nothing from it: allocate the costs by your own rule and write the result back with `PATCH /custom-field-values/batch/{id}`. Needs `custody.read` besides `custom-fields.read`.","x-origonex-scope":"custom-fields.read","x-origonex-unpaginated":"Everything upstream of one lot with its custom values, bounded (at most 2 000 nodes; `truncated` says when).","security":[{"bearerAuth":["custom-fields.read"]}],"parameters":[{"schema":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"required":true,"description":"Opaque entity id (cuid per SA-001; UUID accepted)","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":20,"description":"How many steps upstream to walk, 1 to 20 (default 12)."},"required":false,"description":"How many steps upstream to walk, 1 to 20 (default 12).","name":"maxDepth","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","es","fr","de","it","ja"],"description":"The language of the labels; else the first `Accept-Language` tag this API speaks, else the workspace’s default."},"required":false,"description":"The language of the labels; else the first `Accept-Language` tag this API speaks, else the workspace’s default.","name":"lang","in":"query"}],"responses":{"200":{"description":"The upstream records","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldUpstream"}}}},"401":{"description":"No credentials, or an invalid or expired API key or session (`unauthenticated`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The API key lacks `custom-fields.read` or `custody.read` (`scope_insufficient`), or the caller may not read field capture (`forbidden`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"404":{"description":"No live lot of this workspace has that id (`not_found`), or custom fields are not enabled for this workspace (`custom_fields_not_enabled`)","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/CustomFieldValueProblem"}}}},"422":{"description":"The request did not satisfy the schema (`invalid_body`, `invalid_query_param`, `invalid_path_param`, `invalid_request`).","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded (`rate_limit_exceeded`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"30"},"required":true,"description":"Seconds to wait before retrying.","example":"30"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Temporarily unavailable: no database connection was free in time, or the rate limit could not be checked (`service_unavailable`); `Retry-After` says when to retry.","headers":{"RateLimit-Limit":{"schema":{"type":"string","description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"required":true,"description":"Requests allowed in the current window (IETF draft-ietf-httpapi-ratelimit-headers).","example":"600"},"RateLimit-Remaining":{"schema":{"type":"string","description":"Requests left in the current window.","example":"599"},"required":true,"description":"Requests left in the current window.","example":"599"},"RateLimit-Reset":{"schema":{"type":"string","description":"Seconds until the window resets.","example":"42"},"required":true,"description":"Seconds until the window resets.","example":"42"},"Retry-After":{"schema":{"type":"string","description":"Seconds to wait before retrying.","example":"5"},"required":true,"description":"Seconds to wait before retrying.","example":"5"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{"custody.auditor_opinion.signed":{"post":{"summary":"An auditor's opinion on a lot was signed (or replaced)","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.auditor_opinion.signed"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.auditor_opinion.signed"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"engagementId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"verdict":{"type":"string"},"scope":{"type":"array","items":{"type":"string"}},"signedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"supersedesOpinionId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["id","batchId","engagementId","verdict","scope","signedAt","supersedesOpinionId"],"additionalProperties":false,"description":"An auditor's signed opinion on a lot, or its signed replacement (custody.auditor_opinion.signed). No auditor identity or opinion text."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.auditor_opinion.signed"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.certificate.expired":{"post":{"summary":"A certificate is past its last day","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.certificate.expired"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.certificate.expired"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"alertId":{"type":"string"},"certifier":{"type":"string"},"certifierCustom":{"type":["string","null"]},"certificateNumber":{"type":"string"},"subjectType":{"type":"string"},"subjectId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"validUntil":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"daysLeft":{"type":"integer"},"horizonDays":{"type":"integer","minimum":0}},"required":["id","alertId","certifier","certifierCustom","certificateNumber","subjectType","subjectId","validUntil","daysLeft","horizonDays"],"additionalProperties":false,"description":"A certificate entering its warning horizon (custody.certificate.expiring) or past its last day (custody.certificate.expired)"}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.certificate.expired"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.certificate.expiring":{"post":{"summary":"A certificate entered its warning horizon","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.certificate.expiring"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.certificate.expiring"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"alertId":{"type":"string"},"certifier":{"type":"string"},"certifierCustom":{"type":["string","null"]},"certificateNumber":{"type":"string"},"subjectType":{"type":"string"},"subjectId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"validUntil":{"type":"string","format":"date","description":"ISO 8601 calendar date"},"daysLeft":{"type":"integer"},"horizonDays":{"type":"integer","minimum":0}},"required":["id","alertId","certifier","certifierCustom","certificateNumber","subjectType","subjectId","validUntil","daysLeft","horizonDays"],"additionalProperties":false,"description":"A certificate entering its warning horizon (custody.certificate.expiring) or past its last day (custody.certificate.expired)"}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.certificate.expiring"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.claim.declared":{"post":{"summary":"A certification claim was declared for a lot","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.claim.declared"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.claim.declared"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"scheme":{"type":"string"},"category":{"type":"string"},"percentage":{"type":["integer","null"],"minimum":0,"maximum":100},"certificateCode":{"type":["string","null"]},"supersedesId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"declaredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","batchId","scheme","category","percentage","certificateCode","supersedesId","declaredAt"],"additionalProperties":false,"description":"A certification claim declared for a lot on purchase (custody.claim.declared). No note."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.claim.declared"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.contamination.flagged":{"post":{"summary":"A contamination flag was raised and traced","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.contamination.flagged"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.contamination.flagged"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"sourceKind":{"type":"string","enum":["plot","certificate"],"description":"What was found bad: a plot of land, or a certificate."},"sourceId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"sourceSubjectType":{"type":["string","null"]},"sourceSubjectId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"raisedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"affectedCount":{"type":"integer","minimum":0},"traceTruncated":{"type":"boolean"}},"required":["id","sourceKind","sourceId","sourceSubjectType","sourceSubjectId","reason","raisedAt","affectedCount","traceTruncated"],"additionalProperties":false,"description":"A contamination flag raised and traced down the chain (custody.contamination.flagged). No note."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.contamination.flagged"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.contamination.lifted":{"post":{"summary":"A contamination flag was lifted","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.contamination.lifted"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.contamination.lifted"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"reason":{"type":"string","enum":["deforestation","protected_area","illegal_harvest","land_rights","certificate_suspended","certificate_withdrawn","certificate_invalid","other"],"description":"Why. A plot takes deforestation, protected_area, illegal_harvest or land_rights; a certificate takes certificate_suspended, certificate_withdrawn or certificate_invalid; `other` fits both and needs a note."},"liftedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","reason","liftedAt"],"additionalProperties":false,"description":"A contamination flag lifted (custody.contamination.lifted). No lift reason text."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.contamination.lifted"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.gov_document.applied":{"post":{"summary":"A government transport document was applied to a transport","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.gov_document.applied"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.gov_document.applied"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"documentKind":{"type":"string"},"issuingState":{"type":"string"},"series":{"type":["string","null"]},"number":{"type":"string"},"issuedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"outcome":{"type":"string","enum":["created","matched"]},"transportId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["id","documentKind","issuingState","series","number","issuedAt","outcome","transportId"],"additionalProperties":false,"description":"A government transport document (NF-e, GTA, DOF…) applied to a transport (custody.gov_document.applied). No holder name or tax id."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.gov_document.applied"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.lot.sealed":{"post":{"summary":"A lot's chain was sealed","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.lot.sealed"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.lot.sealed"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"sealId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"sealRoot":{"type":"string"},"sealedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"leafCount":{"type":"integer","minimum":0},"lotCount":{"type":"integer","minimum":0},"supersedesSealId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["batchId","sealId","sealRoot","sealedAt","leafCount","lotCount","supersedesSealId"],"additionalProperties":false,"description":"A lot's chain sealed under one integrity root (custody.lot.sealed)"}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.lot.sealed"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.receipt.recorded":{"post":{"summary":"A receipt was recorded at the destination","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.receipt.recorded"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.receipt.recorded"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transportId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"siteId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"receivingPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"receivedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"outcome":{"type":"string","enum":["accepted","partial","rejected"],"description":"accepted: everything that arrived; partial: part of it (say how much per lot); rejected: none of it."},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"balanceUnit":{"type":["string","null"]},"sentTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"receivedTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"acceptedTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"eventId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"transportLoadId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"unitType":{"type":"string"},"sentQuantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"receivedQuantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"acceptedQuantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"stage":{"type":["string","null"]},"position":{"type":"integer","minimum":0}},"required":["id","transportLoadId","batchId","unitType","sentQuantity","receivedQuantity","acceptedQuantity","stage","position"],"additionalProperties":false}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","transportId","siteId","receivingPartyId","receivedAt","outcome","netKg","balanceUnit","sentTotal","receivedTotal","acceptedTotal","eventId","lines","createdAt"],"additionalProperties":false,"description":"A receipt at the destination (custody.receipt.recorded). No operator, note or rejection reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.receipt.recorded"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transformation.recorded":{"post":{"summary":"A transformation was recorded","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transformation.recorded"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transformation.recorded"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string"},"chainType":{"type":"string"},"commodity":{"type":["string","null"]},"siteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"recordedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"templateVersion":{"type":["string","null"]},"transitionKey":{"type":["string","null"]},"balanceUnit":{"type":["string","null"]},"inputTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"outputTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"lossTotal":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"inputs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"stage":{"type":["string","null"]},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","stage","position"],"additionalProperties":false}},"outputs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"stage":{"type":["string","null"]},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","stage","position"],"additionalProperties":false}},"losses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"kind":{"type":"string"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","kind","quantity","unitType","position"],"additionalProperties":false}}},"required":["id","kind","chainType","commodity","siteId","occurredAt","recordedAt","templateVersion","transitionKey","balanceUnit","inputTotal","outputTotal","lossTotal","reference","inputs","outputs","losses"],"additionalProperties":false,"description":"A transformation: lots consumed, lots made, losses (custody.transformation.recorded). No operator or note."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transformation.recorded"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transport.cancelled":{"post":{"summary":"A transport was cancelled","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transport.cancelled"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transport.cancelled"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"vehicleKind":{"type":["string","null"]},"onFoot":{"type":"boolean"},"originSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"originPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"volumeM3":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","position"],"additionalProperties":false,"description":"A lot on board and the quantity loaded of it"}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","vehicleKind","onFoot","originSiteId","originPartyId","destinationSiteId","destinationPartyId","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","netKg","volumeM3","reference","loads","createdAt","updatedAt"],"additionalProperties":false,"description":"A transport after the action (custody.transport.*). No driver, plate, carrier name, operator, note or cancel reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transport.cancelled"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transport.created":{"post":{"summary":"A transport was created","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transport.created"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transport.created"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"vehicleKind":{"type":["string","null"]},"onFoot":{"type":"boolean"},"originSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"originPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"volumeM3":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","position"],"additionalProperties":false,"description":"A lot on board and the quantity loaded of it"}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","vehicleKind","onFoot","originSiteId","originPartyId","destinationSiteId","destinationPartyId","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","netKg","volumeM3","reference","loads","createdAt","updatedAt"],"additionalProperties":false,"description":"A transport after the action (custody.transport.*). No driver, plate, carrier name, operator, note or cancel reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transport.created"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transport.delivered":{"post":{"summary":"A transport arrived at its destination","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transport.delivered"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transport.delivered"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"vehicleKind":{"type":["string","null"]},"onFoot":{"type":"boolean"},"originSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"originPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"volumeM3":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","position"],"additionalProperties":false,"description":"A lot on board and the quantity loaded of it"}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","vehicleKind","onFoot","originSiteId","originPartyId","destinationSiteId","destinationPartyId","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","netKg","volumeM3","reference","loads","createdAt","updatedAt"],"additionalProperties":false,"description":"A transport after the action (custody.transport.*). No driver, plate, carrier name, operator, note or cancel reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transport.delivered"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transport.departed":{"post":{"summary":"A transport left its origin","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transport.departed"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transport.departed"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"vehicleKind":{"type":["string","null"]},"onFoot":{"type":"boolean"},"originSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"originPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"volumeM3":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","position"],"additionalProperties":false,"description":"A lot on board and the quantity loaded of it"}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","vehicleKind","onFoot","originSiteId","originPartyId","destinationSiteId","destinationPartyId","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","netKg","volumeM3","reference","loads","createdAt","updatedAt"],"additionalProperties":false,"description":"A transport after the action (custody.transport.*). No driver, plate, carrier name, operator, note or cancel reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transport.departed"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.transport.loaded":{"post":{"summary":"A transport was loaded","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.transport.loaded"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.transport.loaded"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"status":{"type":"string","enum":["planned","loaded","in_transit","delivered","cancelled"],"description":"planned → loaded → in_transit → delivered, or cancelled. From loaded on the header is fixed."},"vehicleKind":{"type":["string","null"]},"onFoot":{"type":"boolean"},"originSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"originPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationSiteId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"destinationPartyId":{"type":["string","null"],"format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"plannedDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"plannedArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"loadedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"cancelledAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"netKg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"volumeM3":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"reference":{"type":["string","null"]},"loads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$/u","description":"Decimal number as text (no float rounding)"},"unitType":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","batchId","quantity","unitType","position"],"additionalProperties":false,"description":"A lot on board and the quantity loaded of it"}},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["id","status","vehicleKind","onFoot","originSiteId","originPartyId","destinationSiteId","destinationPartyId","plannedDepartureAt","plannedArrivalAt","loadedAt","actualDepartureAt","actualArrivalAt","cancelledAt","netKg","volumeM3","reference","loads","createdAt","updatedAt"],"additionalProperties":false,"description":"A transport after the action (custody.transport.*). No driver, plate, carrier name, operator, note or cancel reason."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.transport.loaded"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custody.units.created":{"post":{"summary":"Serialised product units were created for a lot","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked.","tags":["Custody webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custody.units.created"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custody.units.created"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"batchId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"lotCode":{"type":"string"},"gtin":{"type":["string","null"]},"count":{"type":"integer","minimum":1},"format":{"type":"string"},"firstSerial":{"type":"string"},"lastSerial":{"type":"string"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["batchId","lotCode","gtin","count","format","firstSerial","lastSerial","createdAt"],"additionalProperties":false,"description":"Serialised product units made for a lot (custody.units.created)"}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custody.units.created"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"custom_field.values_changed":{"post":{"summary":"A record’s custom values changed","description":"Signed with HMAC-SHA256 under the subscription secret (returned once, at creation). Header `X-Origonex-Signature: t=<unix-ms>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, t + \".\" + rawBody))`. Verify over the RAW body bytes, compare in constant time, and refuse a `t` more than 5 minutes from your clock (the replay window). During the overlap window after a secret rotation the header carries one `v1=` per live secret (`t=…,v1=<new>,v1=<old>`); accept the delivery when ANY `v1` matches. Delivery is at least once; dedupe on `eventId`. A 408, 429, 5xx or network error is retried after 30 s, 1, 2, 4 and 8 min; the sixth failure goes to the dead-letter queue at once (~15.5 min after the first try); any other 4xx is not retried. Payloads carry no personal data. An importer’s subscription is bound to one granted supply link: it receives only events whose lots are in that link’s scope, cut by the company’s visibility policy and the link’s fields (closed fields absent), and nothing once the link is revoked. Sent while custom fields are on for the workspace, after each write that stores a value (set, cleared or carried by a correction); `values` holds the record’s values after it. An importer’s subscription receives only the fields the company opened to importers, while its supply link shares «Additional information», and nothing when none is left.","tags":["Custom fields webhooks"],"parameters":[{"schema":{"type":"string","description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>"},"required":true,"description":"t=<unix-ms>,v1=<hex(hmac-sha256(secret, t + \".\" + rawBody))>","name":"x-origonex-signature","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-event-id","in":"header"},{"schema":{"type":"string","enum":["custom_field.values_changed"]},"required":true,"name":"x-origonex-event-kind","in":"header"},{"schema":{"type":"string"},"required":true,"name":"x-origonex-tenant-id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["custom_field.values_changed"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"},"tenantId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"subject":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"additionalProperties":false},"payload":{"type":"object","properties":{"recordKind":{"type":"string","enum":["batch","event","transport","receipt","transformation","site","plot","party","certificate","vehicle","driver"],"description":"The kind of record a field sits on: the chain-of-custody records `batch`, `event`, `transport`, `receipt` and `transformation`, and the master data `site`, `plot` and `party`. Values on `transport`, `receipt`, `transformation` and `site` also need the chain-of-custody programme."},"recordId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"batchIds":{"type":"array","items":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"Opaque entity id (cuid per SA-001; UUID accepted)"},"description":"The lots the record concerns: the lot itself, a transport’s loads, a receipt’s lines, a transformation’s inputs and outputs, an event’s lot. What an importer’s scope is checked against. Empty for a site, a plot or a counterparty: master data concerns no lot, so an importer’s endpoint never receives their changes."},"changed":{"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"description":"The keys this write stored a new value for (cleared ones included)."},"values":{"type":"object","additionalProperties":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,47}$"},"label":{"type":"string"},"labelLang":{"type":"string","description":"The language the label is in (it may be a fallback)."},"type":{"type":"string","enum":["number","money","text","date","single_choice","multi_choice","boolean"],"description":"Fixed at creation. `number` (decimal string with a unit), `money` (`{ amount, currency }`), `text`, `date` (`YYYY-MM-DD`), `single_choice` (an option key), `multi_choice` (sorted option keys), `boolean`."},"value":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"additionalProperties":false},{"type":"null"}]},"display":{"type":"string","description":"The value as text in the reader’s language: a choice’s option label, a number with its places and unit, a sum in its currency, a day. Absent for yes/no (word it in your own copy)."},"unit":{"type":"string"},"currency":{"type":"string"},"fieldVersion":{"type":"integer","minimum":1},"valueId":{"type":"string","format":"entity-id","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u","description":"The stored value. Send it back as `basedOn` when you edit. Company only."},"audiences":{"type":"array","items":{"type":"string","enum":["auditor","importer","buyer","public"],"description":"Who besides the company sees the field. `auditor` is governed here (unlike the rest of the record): an auditor sees a custom field only when it is opened to auditors. `public` takes only number, date, choice and yes/no fields: never money, never free text."},"description":"Company only."},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["key","label","labelLang","type","value","fieldVersion","updatedAt"],"additionalProperties":false,"description":"A custom value as a reader receives it, labelled in the reader’s language."},"description":"The record’s current values after the change; a cleared value is absent."},"requestId":{"type":"string"},"source":{"type":"string","enum":["web","mobile","api","import","carry","system"]},"occurredAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset"}},"required":["recordKind","recordId","batchIds","changed","values","requestId","source","occurredAt"],"additionalProperties":false,"description":"A record’s custom values changed (custom_field.values_changed). Never part of the record’s proof."}},"required":["eventId","kind","occurredAt","tenantId","payload"],"additionalProperties":false,"description":"Webhook delivery body: custom_field.values_changed"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}}}}