{"openapi":"3.1.0","info":{"title":"Nexus Assurance API","summary":"Preview API contract for integrating external systems with Nexus Assurance.","version":"2026-06-18-beta","description":"The beta contract for the Nexus Assurance customer API. Endpoints under `/v1` are backed by the same Nexus Assurance tenant data as the product app and are intended for server-to-server integrations using scoped API tokens.","contact":{"name":"Nexus ReGen","email":"hello@nexusregen.com","url":"https://nexusregen.com"}},"servers":[{"url":"/api","description":"Same-origin API proxy"},{"url":"https://assurance.nexusregen.com/api","description":"Production"}],"tags":[{"name":"Connection","description":"Effective API credential identity and live limits."},{"name":"Projects","description":"Authorised project discovery. Provisioning remains unavailable until the versioned write seam is released."},{"name":"Locations","description":"Authorised physical-location discovery under a project."},{"name":"Sites","description":"Construction sites known to the organisation."},{"name":"Movements","description":"Material movement plans and their compliance state."},{"name":"Loads","description":"Individual vehicle or batch movements under a movement plan."},{"name":"Evidence","description":"Documents and photos submitted against movement requirements or loads."},{"name":"Webhooks","description":"Outbound event subscriptions for customer systems."}],"security":[{"bearerAuth":[]}],"paths":{"/v1/connection":{"get":{"tags":["Connection"],"operationId":"getConnection","summary":"Get the effective API connection","description":"Returns the active credential's effective identity, scopes, project restriction, and enforced limits. It never returns credentials or sandbox lifecycle state.","security":[{"bearerAuth":[]}],"x-nexus-required-scopes":["connection:read"],"x-nexus-lifecycle":"beta","responses":{"200":{"description":"Connection details returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionResponse"},"examples":{"integration":{"value":{"connection":{"organisation":{"id":"org_example","name":"Example organisation"},"integration":{"id":"integration_example","name":"Weighbridge","status":"active"},"environment":"production","scopes":["connection:read","movements:read"],"projectRefs":["PRJ-001"],"capabilities":["connection"],"limits":{"requestsPerMinute":120,"organisationRequestsPerMinute":600,"maxPageSize":100},"contractVersion":"2026-06-18-beta"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/projects":{"get":{"tags":["Projects"],"operationId":"listProjects","summary":"List authorised projects","description":"Lists only projects currently accessible to the credential. This read-only beta slice does not advertise project provisioning or update operations.","x-nexus-required-scopes":["projects:read"],"x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"Projects returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/projects/{projectRef}":{"get":{"tags":["Projects"],"operationId":"getProject","summary":"Get an authorised project","x-nexus-required-scopes":["projects:read"],"x-nexus-lifecycle":"beta","parameters":[{"name":"projectRef","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project returned.","content":{"application/json":{"schema":{"type":"object","required":["project"],"properties":{"project":{"$ref":"#/components/schemas/Project"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/projects/{projectRef}/locations":{"get":{"tags":["Locations"],"operationId":"listProjectLocations","summary":"List authorised project locations","x-nexus-required-scopes":["locations:read"],"x-nexus-lifecycle":"beta","parameters":[{"name":"projectRef","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"Locations returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationResourceListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/locations/{locationRef}":{"get":{"tags":["Locations"],"operationId":"getLocation","summary":"Get an authorised location","x-nexus-required-scopes":["locations:read"],"x-nexus-lifecycle":"beta","parameters":[{"name":"locationRef","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Location returned.","content":{"application/json":{"schema":{"type":"object","required":["location"],"properties":{"location":{"$ref":"#/components/schemas/LocationResource"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/sites":{"get":{"tags":["Sites"],"operationId":"listSites","summary":"List sites","description":"Returns the sites the API token is allowed to access for its organisation.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"Sites returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/movements":{"get":{"tags":["Movements"],"operationId":"listMovements","summary":"List movements","description":"Returns movement plans for the organisation, optionally filtered by site or status.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"name":"siteId","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by Nexus site id."},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/MovementStatus"},"description":"Filter by movement status."}],"responses":{"200":{"description":"Movements returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"tags":["Movements"],"operationId":"createMovement","summary":"Create a movement","description":"Creates a movement case from an external system. Nexus Assurance may still ask follow-up questions in the app before the route is approved.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementCreateRequest"}}}},"responses":{"201":{"description":"Movement created.","headers":{"Nexus-Request-Id":{"$ref":"#/components/headers/NexusRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementCreateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/movements/{movementRef}":{"get":{"tags":["Movements"],"operationId":"getMovement","summary":"Get a movement","description":"Returns the current state of a movement plan by its human-readable reference. The API returns canonical refs such as `ASR-NRG-MP-1-B` and accepts canonical, compact, and tenant-contextual inputs.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/movementRef"}],"responses":{"200":{"description":"Movement returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Movement"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/movements/{movementRef}/loads":{"get":{"tags":["Loads"],"operationId":"listMovementLoads","summary":"List loads for a movement","description":"Returns loads recorded against a movement.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/movementRef"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"Loads returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"tags":["Loads"],"operationId":"createLoad","summary":"Create a load","description":"Adds a scheduled or completed load to a movement plan.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/movementRef"},{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadCreateRequest"}}}},"responses":{"201":{"description":"Load created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Load"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/loads/{loadRef}":{"patch":{"tags":["Loads"],"operationId":"updateLoad","summary":"Update a load","description":"Updates load status, ticket references, or actual quantities from an external logistics system.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/loadRef"},{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadUpdateRequest"}}}},"responses":{"200":{"description":"Load updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Load"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/evidence":{"post":{"tags":["Evidence"],"operationId":"createEvidenceUpload","summary":"Create an evidence upload","description":"Creates an evidence record and returns a time-limited upload URL. File bytes are uploaded directly to Nexus-managed storage rather than through this API route.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceUploadRequest"}}}},"responses":{"201":{"description":"Evidence upload prepared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceUploadResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/evidence/{evidenceId}/complete":{"post":{"tags":["Evidence"],"operationId":"completeEvidenceUpload","summary":"Complete an evidence upload","description":"Confirms that a file has been uploaded, then queues Nexus Assurance review where appropriate.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/evidenceId"},{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceCompleteRequest"}}}},"responses":{"200":{"description":"Evidence upload completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Evidence"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/webhook-endpoints":{"get":{"tags":["Webhooks"],"operationId":"listWebhookEndpoints","summary":"List webhook endpoints","description":"Returns outbound webhook endpoints configured for the organisation.","x-nexus-lifecycle":"beta","responses":{"200":{"description":"Webhook endpoints returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"tags":["Webhooks"],"operationId":"createWebhookEndpoint","summary":"Create a webhook endpoint","description":"Registers a customer endpoint for outbound Nexus Assurance events.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreateRequest"}}}},"responses":{"201":{"description":"Webhook endpoint created. The signing secret is returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/webhook-endpoints/{webhookEndpointId}":{"delete":{"tags":["Webhooks"],"operationId":"deleteWebhookEndpoint","summary":"Delete a webhook endpoint","description":"Disables and removes an outbound webhook endpoint.","x-nexus-lifecycle":"beta","parameters":[{"$ref":"#/components/parameters/webhookEndpointId"}],"responses":{"204":{"description":"Webhook endpoint deleted."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Nexus API token","description":"Use `Authorization: Bearer nxapi_...`. API tokens are scoped to one Nexus Assurance organisation."}},"parameters":{"idempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Recommended for POST and PATCH requests. Reusing the same key returns the original result for the same operation."},"limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Maximum number of records to return."},"cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque pagination cursor returned by a previous response."},"movementRef":{"name":"movementRef","in":"path","required":true,"schema":{"type":"string","pattern":"^(?:(?:ASR-)?[A-Z0-9]{2,6}-)?MP-[0-9]+-[0-9A-HJKMNP-TV-Z]$|^(?:ASR)?[A-Z0-9]{2,6}MP[0-9]+[0-9A-HJKMNP-TV-Z]$|^MP[0-9]+[0-9A-HJKMNP-TV-Z]$"},"example":"ASR-NRG-MP-1-B"},"loadRef":{"name":"loadRef","in":"path","required":true,"schema":{"type":"string","pattern":"^(?:(?:ASR-)?[A-Z0-9]{2,6}-)?LD-[0-9]+-[0-9A-HJKMNP-TV-Z]$|^(?:ASR)?[A-Z0-9]{2,6}LD[0-9]+[0-9A-HJKMNP-TV-Z]$|^LD[0-9]+[0-9A-HJKMNP-TV-Z]$"},"example":"ASR-NRG-LD-1-V"},"evidenceId":{"name":"evidenceId","in":"path","required":true,"schema":{"type":"string"},"example":"k170a5cd6x0jv8a9s9e8h8f6n57k9q7m"},"webhookEndpointId":{"name":"webhookEndpointId","in":"path","required":true,"schema":{"type":"string"},"example":"k170a5cd6x0jv8a9s9e8h8f6n57k9q7m"}},"headers":{"NexusRequestId":{"description":"Stable request id for support and audit correlation.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"The request body or parameters are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"The API token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"The API token does not have the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"The requested resource was not found for this organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"The request conflicts with existing state or idempotency history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"The token or organisation has exceeded its rate limit.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ConnectionResponse":{"type":"object","required":["connection"],"properties":{"connection":{"type":"object","required":["organisation","integration","environment","scopes","projectRefs","capabilities","limits","contractVersion"],"properties":{"organisation":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"integration":{"type":"object","required":["id","name","status"],"properties":{"id":{"type":["string","null"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","legacy"]}}},"environment":{"type":"string","enum":["production","sandbox"]},"scopes":{"type":"array","items":{"type":"string"}},"projectRefs":{"type":["array","null"],"items":{"type":"string"}},"capabilities":{"type":"array","items":{"type":"string"}},"limits":{"type":"object","required":["requestsPerMinute","organisationRequestsPerMinute","maxPageSize"],"properties":{"requestsPerMinute":{"type":"integer","minimum":1},"organisationRequestsPerMinute":{"type":"integer","minimum":1},"maxPageSize":{"type":"integer","minimum":1}}},"contractVersion":{"type":"string","const":"2026-06-18-beta"},"sandboxEpoch":{"type":"integer","minimum":1}}}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"invalid_request"},"message":{"type":"string","example":"The `siteId` field is required."},"details":{"type":"object","additionalProperties":true},"requestId":{"type":"string","example":"req_01JY7K6H8Q7VA8SM0EWK"}}}}},"PageInfo":{"type":"object","required":["hasMore"],"properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]}}},"Project":{"type":"object","required":["id","ref","name","status","jurisdiction","createdAt"],"properties":{"id":{"type":"string"},"ref":{"type":"string","example":"ASR-NRG-PRJ-1-C"},"name":{"type":"string"},"status":{"type":"string","enum":["mobilising","active","on_hold","completed"]},"jurisdiction":{"type":"string","enum":["england","wales","scotland","northern_ireland","uk","unknown"]},"address":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ProjectListResponse":{"type":"object","required":["data","page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"page":{"$ref":"#/components/schemas/PageInfo"}}},"LocationResource":{"type":"object","required":["id","ref","projectRef","name","status","jurisdiction","createdAt"],"properties":{"id":{"type":"string"},"ref":{"type":"string","example":"ASR-NRG-LOC-1-R"},"projectRef":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["mobilising","active","on_hold","completed"]},"address":{"type":"string"},"postcode":{"type":"string"},"jurisdiction":{"type":"string","enum":["england","wales","scotland","northern_ireland","uk","unknown"]},"createdAt":{"type":"string","format":"date-time"}}},"LocationResourceListResponse":{"type":"object","required":["data","page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LocationResource"}},"page":{"$ref":"#/components/schemas/PageInfo"}}},"Site":{"type":"object","required":["id","ref","name","status","createdAt"],"properties":{"id":{"type":"string","example":"site_01JY7J2QF5W37H5G7BHK"},"ref":{"type":"string","example":"ASR-NRG-LOC-1-R"},"slug":{"type":"string","example":"northbank-remediation"},"name":{"type":"string","example":"Northbank remediation"},"status":{"type":"string","enum":["mobilising","active","on_hold","completed"]},"address":{"type":"string","example":"Northbank Road, Bristol"},"jurisdiction":{"type":"string","enum":["england","wales","scotland","northern_ireland","uk","unknown"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SiteListResponse":{"type":"object","required":["data","page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Site"}},"page":{"$ref":"#/components/schemas/PageInfo"}}},"MovementStatus":{"type":"string","enum":["draft_intake","awaiting_required_info","route_hypothesised","evidence_requested","evidence_under_review","requires_human_review","ready_for_approval","approved","movement_in_progress","completed","blocked","superseded","archived"]},"RouteKind":{"type":"string","enum":["unknown","dowcop_candidate","waste_movement_to_authorised_receiver","landfill_route_possible","environmental_permit_or_exemption_possible","recycled_aggregate_end_of_waste_possible","product_reuse_possible","hazardous_or_specialist_review_required","blocked_insufficient_information"]},"Material":{"type":"object","required":["description"],"properties":{"description":{"type":"string","example":"Clean naturally occurring clay and subsoil"},"ewcCode":{"type":"string","example":"17 05 04"},"quantity":{"type":"number","example":1200},"unit":{"type":"string","enum":["tonnes","m3","loads"],"default":"tonnes"},"contaminationNotes":{"type":"string"}}},"Location":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Northbank remediation"},"siteId":{"type":"string"},"locationId":{"type":"string","description":"Explicit Nexus location identity; never inferred from a display name."},"address":{"type":"string"},"postcode":{"type":"string"},"gridReference":{"type":"string"}}},"MovementSummary":{"type":"object","required":["id","ref","status","title","siteId","createdAt","updatedAt","resourceVersion"],"properties":{"id":{"type":"string"},"ref":{"type":"string","example":"ASR-NRG-MP-1-B"},"title":{"type":"string","example":"Northbank subsoil to Avon reuse site"},"siteId":{"type":"string","example":"site_01JY7J2QF5W37H5G7BHK"},"status":{"$ref":"#/components/schemas/MovementStatus"},"routeKind":{"$ref":"#/components/schemas/RouteKind"},"material":{"$ref":"#/components/schemas/Material"},"project":{"type":"object","properties":{"id":{"type":"string"},"ref":{"type":"string"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resourceVersion":{"type":"integer","minimum":1}}},"Movement":{"allOf":[{"$ref":"#/components/schemas/MovementSummary"},{"type":"object","required":["origin","destination"],"properties":{"origin":{"$ref":"#/components/schemas/Location"},"destination":{"$ref":"#/components/schemas/Location"},"plannedStartDate":{"type":"string","format":"date"},"plannedEndDate":{"type":"string","format":"date"},"externalId":{"type":"string","description":"Customer system identifier."},"evidenceRequirements":{"type":"array","items":{"$ref":"#/components/schemas/EvidenceRequirement"}}}}]},"MovementListResponse":{"type":"object","required":["data","page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MovementSummary"}},"page":{"$ref":"#/components/schemas/PageInfo"}}},"MovementCreateRequest":{"type":"object","required":["siteId","origin","destination","material"],"additionalProperties":false,"properties":{"siteId":{"type":"string"},"title":{"type":"string"},"externalId":{"type":"string"},"origin":{"$ref":"#/components/schemas/Location"},"destination":{"$ref":"#/components/schemas/Location"},"material":{"$ref":"#/components/schemas/Material"},"plannedStartDate":{"type":"string","format":"date"},"plannedEndDate":{"type":"string","format":"date"},"notes":{"type":"string"}}},"MovementCreateResponse":{"type":"object","required":["movement"],"properties":{"movement":{"$ref":"#/components/schemas/Movement"},"warnings":{"type":"array","items":{"type":"string"}}}},"LoadStatus":{"type":"string","enum":["scheduled","in_transit","delivered","evidence_due","verified","rejected","cancelled"]},"Load":{"type":"object","required":["id","ref","movementRef","status","createdAt","updatedAt","resourceVersion"],"properties":{"id":{"type":"string"},"ref":{"type":"string","example":"ASR-NRG-LD-1-V"},"movementRef":{"type":"string","example":"ASR-NRG-MP-1-B"},"externalId":{"type":"string"},"status":{"$ref":"#/components/schemas/LoadStatus"},"vehicleRegistration":{"type":"string","example":"AB12 CDE"},"haulierName":{"type":"string"},"carrierRegistration":{"type":"string"},"ticketReference":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string","enum":["tonnes","m3","loads"]},"scheduledAt":{"type":"string","format":"date-time"},"departedAt":{"type":"string","format":"date-time"},"deliveredAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resourceVersion":{"type":"integer","minimum":1}}},"LoadCreateRequest":{"type":"object","additionalProperties":false,"properties":{"externalId":{"type":"string"},"status":{"$ref":"#/components/schemas/LoadStatus","description":"`verified` and `rejected` are outcomes of document review, not something an integration can set: they are refused with a 400. Upload the load's evidence and it is reviewed."},"vehicleRegistration":{"type":"string"},"haulierName":{"type":"string"},"carrierRegistration":{"type":"string"},"ticketReference":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string","enum":["tonnes","m3","loads"]},"scheduledAt":{"type":"string","format":"date-time"}}},"LoadUpdateRequest":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"status":{"$ref":"#/components/schemas/LoadStatus","description":"`verified` and `rejected` are outcomes of document review, not something an integration can set: they are refused with a 400. Upload the load's evidence and it is reviewed."},"ticketReference":{"type":"string"},"quantity":{"type":"number"},"departedAt":{"type":"string","format":"date-time"},"deliveredAt":{"type":"string","format":"date-time"}}},"LoadListResponse":{"type":"object","required":["data","page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Load"}},"page":{"$ref":"#/components/schemas/PageInfo"}}},"EvidenceKind":{"type":"string","enum":["mmp","qp_declaration","waste_transfer_note","hazardous_waste_consignment_note","carrier_registration","receiver_authorisation","permit_or_exemption","weighbridge_ticket","lab_report","wac_or_basic_characterisation","acceptance_receipt","photo_evidence","human_confirmation","human_approval","other"]},"EvidenceStatus":{"type":"string","enum":["required","requested","submitted","partially_satisfied","satisfied_for_workflow","rejected","waived_by_human","superseded"]},"EvidenceRequirement":{"type":"object","required":["id","kind","title","status","required"],"properties":{"id":{"type":"string"},"kind":{"$ref":"#/components/schemas/EvidenceKind"},"title":{"type":"string"},"description":{"type":"string"},"status":{"$ref":"#/components/schemas/EvidenceStatus"},"required":{"type":"boolean"}}},"Evidence":{"type":"object","required":["id","kind","status","fileName","createdAt"],"properties":{"id":{"type":"string","example":"k170a5cd6x0jv8a9s9e8h8f6n57k9q7m"},"movementRef":{"type":"string","example":"ASR-NRG-MP-1-B"},"loadRef":{"type":"string","example":"ASR-NRG-LD-1-V"},"kind":{"$ref":"#/components/schemas/EvidenceKind"},"status":{"$ref":"#/components/schemas/EvidenceStatus"},"fileName":{"type":"string","example":"wtn-4821.pdf"},"contentType":{"type":"string","example":"application/pdf"},"sizeBytes":{"type":"integer","minimum":0},"sha256":{"type":"string"},"reviewSummary":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"EvidenceUploadRequest":{"type":"object","required":["kind","fileName","contentType"],"additionalProperties":false,"properties":{"movementRef":{"type":"string","example":"ASR-NRG-MP-1-B"},"loadRef":{"type":"string","example":"ASR-NRG-LD-1-V"},"kind":{"$ref":"#/components/schemas/EvidenceKind"},"fileName":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"integer","minimum":0},"sha256":{"type":"string","description":"Optional client-computed content hash."}}},"EvidenceUploadResponse":{"type":"object","required":["evidence","upload"],"properties":{"evidence":{"$ref":"#/components/schemas/Evidence"},"upload":{"type":"object","required":["url","method","expiresAt"],"properties":{"url":{"type":"string","format":"uri"},"method":{"type":"string","enum":["PUT"]},"headers":{"type":"object","additionalProperties":{"type":"string"}},"expiresAt":{"type":"string","format":"date-time"}}}}},"EvidenceCompleteRequest":{"type":"object","additionalProperties":false,"properties":{"sha256":{"type":"string"},"sizeBytes":{"type":"integer","minimum":0}}},"WebhookEventType":{"type":"string","enum":["movement.created","movement.status_changed","movement.completed","load.created","load.status_changed","evidence.submitted","evidence.reviewed"]},"WebhookEndpoint":{"type":"object","required":["id","url","eventTypes","enabled","createdAt"],"properties":{"id":{"type":"string","example":"k170a5cd6x0jv8a9s9e8h8f6n57k9q7m"},"url":{"type":"string","format":"uri","example":"https://example.com/nexus/webhook"},"description":{"type":"string"},"eventTypes":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookEndpointCreateRequest":{"type":"object","required":["url","eventTypes"],"additionalProperties":false,"properties":{"url":{"type":"string","format":"uri"},"description":{"type":"string"},"eventTypes":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/WebhookEventType"}}}},"WebhookEndpointCreateResponse":{"type":"object","required":["endpoint","signingSecret"],"properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"},"signingSecret":{"type":["string","null"],"example":"whsec_01JY7M6D5A9QY4PZ7FQ6","description":"Returned once on initial creation. Idempotency replays return `null` rather than storing the plaintext secret at rest."}}},"WebhookEndpointListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}}