{"openapi":"3.1.0","info":{"title":"Inventory API","version":"1.15.0","description":"Organization-scoped API for configurable inventory structures, localized content, indoor 3D room scans, location-aware stock, cycle counts, assignments, CSV exchange, typed custom fields, label setups, media, AI, outgoing integration webhooks, and data quality. User-bound credentials may select one of their memberships with X-Organization-ID. Standalone API tokens are pinned to their issuing organization.","license":{"name":"MIT License","identifier":"MIT"}},"servers":[{"url":"/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Authentication","description":"Native sign-in, token revocation, and scope discovery."},{"name":"Organizations","description":"Membership discovery, active-organization selection, creation, and administration."},{"name":"Access control","description":"Session-administered roles, granular permissions, and conditional inventory-item access rules."},{"name":"Resources","description":"Inventory item creation, lookup, retrieval, and lifecycle."},{"name":"Inventory structure","description":"Configurable inventory types, relationship types, and directed resource relationships."},{"name":"Data exchange","description":"Idempotent CSV import and complete CSV export."},{"name":"Custom fields","description":"Typed field definitions, including filtered record references, for inventory items and serialized stock units."},{"name":"Content translations","description":"Canonical content languages and field-aware AI translations."},{"name":"Label setups","description":"Reusable physical dimensions and positioned content for printed inventory labels."},{"name":"Stock","description":"Stock health, configuration, movements, and serialized units."},{"name":"Inventory cycles","description":"Recurring count policies, due-count queues, and stock reconciliation."},{"name":"Assignments","description":"Checkout, assignment, reservation, return, and cancellation workflows."},{"name":"Manufacturing","description":"Bills of materials and atomic assembly builds."},{"name":"Purchasing","description":"Purchase orders, incoming quantities, and stock receipts."},{"name":"Scan workflows","description":"Configurable scan actions and execution."},{"name":"Media","description":"Resource images, metadata, and ordering."},{"name":"Spatial rooms","description":"Versioned RoomPlan scenes, native AR world-map assets, and measured indoor item placements."},{"name":"AI","description":"Visual inventory recognition, counting, item analysis, and generated covers."},{"name":"Insights","description":"Workspace statistics and duplicate detection."},{"name":"Notifications","description":"Session-scoped in-app inbox, anti-noise preferences, Web Push subscriptions, and preview-only channel tests."},{"name":"Webhooks","description":"Session-administered outgoing integration events with durable at-least-once delivery, HMAC signatures, retry history, and manual replay."}],"paths":{"/notifications":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Notifications"],"summary":"List the current user's in-app notifications","description":"The inbox is always available. Events are deduplicated using the user's configured cooldown; external delivery is not required.","security":[{"adminSession":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":30}},{"name":"unreadOnly","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Notifications plus the complete unread count","content":{"application/json":{"schema":{"type":"object","required":["notifications","unread"],"properties":{"notifications":{"type":"array","items":{"$ref":"#/components/schemas/Notification"}},"unread":{"type":"integer","minimum":0}}}}}},"403":{"description":"An authenticated browser session is required"}}}},"/notifications/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Notifications"],"summary":"Mark one notification read","security":[{"adminSession":[]}],"responses":{"200":{"description":"Notification marked read"},"404":{"description":"Notification not found for this user"}}}},"/notifications/read-all":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Notifications"],"summary":"Mark every notification for the current user read","security":[{"adminSession":[]}],"responses":{"200":{"description":"Number of updated inbox entries"}}}},"/notifications/preferences":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Notifications"],"summary":"Read personal anti-noise and channel preferences","security":[{"adminSession":[]}],"responses":{"200":{"description":"Preferences, redacted runtime channel state, and Push subscription count"}}},"patch":{"tags":["Notifications"],"summary":"Update personal notification preferences","description":"External channels default off and must be explicitly enabled. Destination URLs remain server environment variables and are never accepted by this endpoint.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencePatch"}}}},"responses":{"200":{"description":"Preferences updated"},"422":{"description":"Invalid thresholds","cadence":null,"fields":null,"locale":null,"or channel opt-ins":null}}}},"/notifications/push-subscriptions":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Notifications"],"summary":"Subscribe the current browser to Web Push","description":"Subscription endpoint and key material are encrypted before storage using the deployment notification encryption key.","security":[{"adminSession":[]}],"responses":{"201":{"description":"Encrypted subscription stored"},"503":{"description":"VAPID or at-rest encryption is not configured"}}},"delete":{"tags":["Notifications"],"summary":"Revoke the current browser's Web Push subscription","security":[{"adminSession":[]}],"responses":{"200":{"description":"Subscription revoked when present"}}}},"/notifications/test":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Notifications"],"summary":"Preview one delivery channel without sending","description":"Dry-run only. This endpoint never invokes SMTP, Web Push, Slack, Teams, or generic webhook transports.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["channel"],"properties":{"channel":{"type":"string","enum":["email","push","slack","teams","webhook"]}}}}}},"responses":{"200":{"description":"Redacted sample payload with dryRun true"}}}},"/notifications/run":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Notifications"],"summary":"Run notification detection and due digest dispatch","description":"Invokes one deduplicated detector/dispatcher cycle. Authenticate with `Authorization: Bearer NOTIFICATION_CRON_SECRET`, or with an authenticated browser session that has `tokens.manage`. Safe retries rely on cooldown, inbox uniqueness, and dispatch dedupe keys.","security":[{"cronSecret":[]},{"adminSession":[]}],"responses":{"200":{"description":"Detection and dispatch counters"},"401":{"description":"Missing or invalid cron secret or browser session"},"403":{"description":"Browser session lacks tokens.manage"}}}},"/webhooks":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Webhooks"],"summary":"List outgoing webhook endpoints","description":"Requires an authenticated browser session with `webhooks.manage`. Stored targets are redacted in responses, and API bearer tokens are not accepted.","security":[{"adminSession":[]}],"responses":{"200":{"description":"Configured webhook endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"}}},"post":{"tags":["Webhooks"],"summary":"Create an outgoing webhook endpoint","description":"Requires `webhooks.manage`. The signing secret is returned only by this response; store it before leaving the page.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Webhook endpoint created and its signing secret disclosed once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreatedResponse"}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"422":{"description":"Invalid name","target URL":null,"event subscription":null,"or enabled state":null},"503":{"description":"Webhook at-rest encryption is not configured"}}}},"/webhooks/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/WebhookId"}],"get":{"tags":["Webhooks"],"summary":"Retrieve one outgoing webhook endpoint","description":"Requires an authenticated browser session with `webhooks.manage`. The target is redacted and the signing secret is never returned.","security":[{"adminSession":[]}],"responses":{"200":{"description":"Webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Invalid webhook endpoint identifier"}}},"patch":{"tags":["Webhooks"],"summary":"Update an outgoing webhook endpoint","description":"Requires `webhooks.manage`. Submit at least one field. A new target must be supplied in full because stored targets are only returned in redacted form.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPatch"}}}},"responses":{"200":{"description":"Webhook endpoint updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Empty or invalid webhook endpoint update"},"503":{"description":"Webhook at-rest encryption is not configured"}}},"delete":{"tags":["Webhooks"],"summary":"Delete an outgoing webhook endpoint","description":"Requires an authenticated browser session with `webhooks.manage`.","security":[{"adminSession":[]}],"responses":{"204":{"description":"Webhook endpoint deleted"},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Invalid webhook endpoint identifier"}}}},"/webhooks/{id}/test":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/WebhookId"}],"post":{"tags":["Webhooks"],"summary":"Enqueue a real signed test delivery","description":"Requires `webhooks.manage`. Unlike notification channel previews, this creates an event and sends an actual HTTP request through the durable delivery queue.","security":[{"adminSession":[]}],"responses":{"202":{"description":"Test event and delivery accepted for asynchronous processing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Invalid webhook endpoint identifier"},"503":{"description":"Webhook at-rest encryption is not configured"}}}},"/webhooks/{id}/rotate-secret":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/WebhookId"}],"post":{"tags":["Webhooks"],"summary":"Rotate a webhook signing secret","description":"Requires `webhooks.manage`. The replacement secret is returned only by this response and cannot be read again.","security":[{"adminSession":[]}],"responses":{"200":{"description":"Signing secret rotated and disclosed once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSecretResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Invalid webhook endpoint identifier"},"503":{"description":"Webhook at-rest encryption is not configured"}}}},"/webhooks/{id}/deliveries":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/WebhookId"}],"get":{"tags":["Webhooks"],"summary":"List delivery attempts for one webhook endpoint","description":"Requires an authenticated browser session with `webhooks.manage`.","security":[{"adminSession":[]}],"parameters":[{"name":"limit","in":"query","description":"Maximum number of recent deliveries returned; values above 100 are capped.","schema":{"type":"integer","minimum":1,"default":50}}],"responses":{"200":{"description":"Recent deliveries and their retry state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryListResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Webhook endpoint not found"},"422":{"description":"Invalid webhook endpoint identifier or delivery limit"}}}},"/webhooks/{id}/deliveries/{deliveryId}/retry":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/WebhookId"},{"$ref":"#/components/parameters/WebhookDeliveryId"}],"post":{"tags":["Webhooks"],"summary":"Manually retry a failed delivery","description":"Requires `webhooks.manage` and an enabled endpoint. The same event identity is retained so receivers can deduplicate an at-least-once replay.","security":[{"adminSession":[]}],"responses":{"202":{"description":"Delivery accepted for asynchronous retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"An authenticated browser session is required"},"403":{"description":"Browser session lacks webhooks.manage"},"404":{"description":"Enabled webhook endpoint or failed delivery not found"},"422":{"description":"Invalid webhook endpoint or delivery identifier"}}}},"/webhooks/run":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Webhooks"],"summary":"Process due outgoing webhook deliveries","description":"Runs one bounded delivery cycle for deployments without the built-in worker. Authenticate only with `Authorization: Bearer WEBHOOK_CRON_SECRET`; browser sessions and API tokens are not accepted.","security":[{"webhookCronSecret":[]}],"parameters":[{"name":"limit","in":"query","description":"Maximum number of due deliveries claimed during this bounded cycle.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Due deliveries processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRunResponse"}}}},"401":{"description":"Missing","invalid":null,"or unconfigured webhook cron secret":null},"422":{"description":"Limit must be an integer between 1 and 100"}}}},"/spatial-structures":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Spatial rooms"],"summary":"List buildings and their active indoor-scan coverage","responses":{"200":{"description":"Structures with active room, floor, coordinate-space, and compatible-bounds counts","content":{"application/json":{"schema":{"type":"object","required":["structures"],"properties":{"structures":{"type":"array","items":{"$ref":"#/components/schemas/SpatialStructureSummary"}}}}}}}}},"post":{"tags":["Spatial rooms"],"summary":"Create a building or other multi-room structure","description":"Requires write scope. A structure may also be created atomically by the first grouped room-scan upload.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpatialStructureCreate"}}}},"responses":{"201":{"description":"Structure created"},"409":{"description":"The client-provided structure id already exists"},"422":{"description":"Invalid structure or georeference"}}}},"/spatial-structures/{structureId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"structureId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Spatial rooms"],"summary":"Retrieve active rooms grouped by floor and AR coordinate space","responses":{"200":{"description":"Structure, coordinate spaces, floors, room scenes, and placements"},"404":{"description":"Spatial structure not found"},"422":{"description":"Invalid spatial structure identifier"}}},"patch":{"tags":["Spatial rooms"],"summary":"Update a structure's name or canonical map anchor","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpatialStructurePatch"}}}},"responses":{"200":{"description":"Structure updated"},"404":{"description":"Spatial structure not found"},"422":{"description":"Invalid structure change or georeference"}}}},"/room-scans":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Spatial rooms"],"summary":"List active 3D room scans","parameters":[{"name":"includeSuperseded","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Room scans ordered by capture time","content":{"application/json":{"schema":{"type":"object","required":["scans"],"properties":{"scans":{"type":"array","items":{"$ref":"#/components/schemas/RoomScanSummary"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"}}},"post":{"tags":["Spatial rooms"],"summary":"Upload a normalized RoomPlan scan and its native assets","description":"Requires write scope. The client-generated scan id makes exact retries idempotent. The referenced resource must have type `place`. RGB keyframes carry ARKit camera poses and intrinsics in the scan's coordinate space; each JPEG part name must match its metadata fileField.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["id","roomResourceId","capturedAt","scene","worldMap","model"],"properties":{"id":{"type":"string","format":"uuid"},"roomResourceId":{"type":"string","format":"uuid"},"capturedAt":{"type":"string","format":"date-time"},"deviceModel":{"type":"string","maxLength":120},"structureId":{"type":"string","format":"uuid","description":"Groups this room into a building. The first upload may create this id."},"structureName":{"type":"string","minLength":1,"maxLength":240},"coordinateSpaceId":{"type":"string","format":"uuid","description":"Shared by rooms captured or relocalized in the same ARKit world frame. Never reuse it for independently captured coordinate systems."},"floorIdentifier":{"type":"string","minLength":1,"maxLength":120},"floorIndex":{"type":"integer","minimum":-1000,"maximum":10000},"roomIdentifier":{"type":"string","minLength":1,"maxLength":120},"georeference":{"type":"string","contentMediaType":"application/json","description":"UTF-8 JSON encoding of SpatialGeoreference for this coordinate space."},"scene":{"type":"string","description":"UTF-8 JSON encoding of the RoomScene schema.","contentMediaType":"application/json"},"worldMap":{"type":"string","format":"binary","description":"NSSecureCoding archive of the ARWorldMap used for later relocalization."},"model":{"type":"string","format":"binary","description":"Original RoomPlan USDZ mesh."},"structureModel":{"type":"string","format":"binary","description":"Optional combined multi-room USDZ model produced by StructureBuilder."},"guideImage":{"type":"string","format":"binary"},"keyframes":{"type":"string","contentMediaType":"application/json","description":"UTF-8 JSON array of at most 32 RoomCameraKeyframeInput records. Each record references one JPEG multipart field named keyframe:<frame-id>."},"texturedMesh":{"type":"string","format":"binary","description":"Optional self-contained, bounded GLB v2 textured room mesh whose vertices are already in the scan's ARKit world frame in metres (model/gltf-binary, maximum 80 MB). External resources, unsafe accessor ranges/counts, oversized embedded textures, and unsupported required codecs are rejected."},"gaussianSplat":{"type":"string","format":"binary","description":"Optional bounded binary-little-endian, vertex-only PLY Gaussian Splat whose vertices are already in the scan's ARKit world frame in metres (maximum 80 MB)."}}}}}},"responses":{"200":{"description":"Exact scan-id replay; no duplicate revision was created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomScanUploadResult"}}}},"201":{"description":"Scan created and made the active revision for its room","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomScanUploadResult"}}}},"404":{"description":"Room resource not found"},"409":{"description":"Scan id belongs to another room"},"411":{"description":"Content-Length is required before buffering the multipart upload"},"413":{"description":"Combined upload exceeds the configured room-scan limit"},"415":{"description":"A keyframe or photorealistic derivative has an unsafe MIME type/extension pair"},"422":{"description":"Invalid scene","identifier":null,"date":null,"or non-place resource":null}}}},"/room-scans/{scanId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Spatial rooms"],"summary":"Retrieve a web-viewer scene with positioned inventory","responses":{"200":{"description":"Normalized room scene, assets, and current placements attached to this revision","content":{"application/json":{"schema":{"type":"object","required":["scene"],"properties":{"scene":{"$ref":"#/components/schemas/RoomSceneManifest"}}}}}},"404":{"description":"Room scan not found"},"422":{"description":"Invalid room scan identifier"}}}},"/room-scans/{scanId}/layout":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Spatial rooms"],"summary":"Position one room inside its floor layout","description":"Requires spatial management permission. The transform is a column-major world-from-model matrix in metres. Set it to null to restore automatic floor arrangement.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomLayoutTransformPatch"}}}},"responses":{"200":{"description":"Room layout position updated"},"404":{"description":"Room scan not found"},"422":{"description":"Invalid room scan identifier or layout transform"}}}},"/room-scans/{scanId}/assets/{kind}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","enum":["world_map","model_usdz","structure_model","guide_image","textured_mesh","gaussian_splat"]}}],"get":{"tags":["Spatial rooms"],"summary":"Download an authenticated native room-scan asset","responses":{"200":{"description":"Binary asset returned as an attachment"},"404":{"description":"Scan asset or stored bytes not found"},"422":{"description":"Invalid room scan identifier"}}},"put":{"tags":["Spatial rooms"],"summary":"Attach or replace a photorealistic room derivative","description":"Accepts raw GLB bytes for textured_mesh or raw bounded PLY bytes for gaussian_splat. Vertices must already use the scan's shared ARKit world frame (metres, right-handed, Y-up); no alignment transform is inferred. The web client renders PLY as a bounded point-splat preview; textured GLB is the full photorealistic path. This mutable enrichment does not change the idempotent identity of the original room capture. Content-Length is required before the server buffers the body.","requestBody":{"required":true,"content":{"model/gltf-binary":{"schema":{"type":"string","format":"binary","maxLength":80000000}},"application/octet-stream":{"schema":{"type":"string","format":"binary","maxLength":80000000}}}},"responses":{"200":{"description":"Existing derivative replaced"},"201":{"description":"Derivative attached"},"404":{"description":"Room scan or mutable asset kind not found"},"411":{"description":"Content-Length is required"},"413":{"description":"Asset exceeds its 80 MB limit"},"415":{"description":"Content-Type does not match the asset kind"},"422":{"description":"Invalid identifier or malformed GLB/PLY data"}}}},"/room-scans/{scanId}/keyframes/{keyframeId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"keyframeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Spatial rooms"],"summary":"Download an authenticated RGB localization keyframe","responses":{"200":{"description":"Inline JPEG keyframe","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Keyframe or stored bytes not found"},"422":{"description":"Invalid room scan or keyframe identifier"}}}},"/room-scans/{scanId}/placements/{resourceId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"resourceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"put":{"tags":["Spatial rooms"],"summary":"Create or replace an item's current indoor 3D placement","description":"The scan must still be the active revision. Coordinates use its ARKit world frame in metres.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpatialPlacementInput"}}}},"responses":{"200":{"description":"Placement saved"},"404":{"description":"Room scan or inventory item not found"},"409":{"description":"Room scan was superseded and the item must be relocalized"},"422":{"description":"Invalid identifier or placement"}}},"delete":{"tags":["Spatial rooms"],"summary":"Remove an item's placement from this scan","responses":{"204":{"description":"Placement removed"},"404":{"description":"Placement not found"},"422":{"description":"Invalid identifier"}}}},"/auth/login":{"post":{"tags":["Authentication"],"summary":"Sign in a native client with a local account","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","maxLength":320},"password":{"type":"string","format":"password","minLength":1,"maxLength":72},"deviceName":{"type":"string","minLength":1,"maxLength":80,"default":"iOS"},"organizationId":{"type":"string","format":"uuid","description":"Optional membership to select when signing in. The first membership is used when omitted."}}}}}},"responses":{"201":{"description":"Signed in and issued a revocable user-bound bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeLoginResponse"}}}},"400":{"description":"Invalid login request"},"401":{"description":"Email or password is incorrect"},"429":{"description":"Too many login attempts","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}}}}},"/auth/logout":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Authentication"],"summary":"Revoke the current bearer token","responses":{"204":{"description":"Token revoked"},"401":{"description":"Missing or invalid bearer token"}}}},"/auth/capabilities":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Authentication"],"summary":"Inspect the authenticated token's available scopes","responses":{"200":{"description":"Token identity and capabilities","content":{"application/json":{"schema":{"type":"object","required":["name","principal","scopes","role","roleName","permissions","organization","organizations"],"properties":{"name":{"type":"string"},"principal":{"type":"string","description":"Opaque organization-scoped principal identifier for binding durable client state."},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","ai"]}},"role":{"type":["string","null"],"pattern":"^[a-z][a-z0-9_-]{0,63}$","description":"Stable role key for user-bound identities; null for standalone API tokens."},"roleName":{"type":["string","null"],"description":"Human-readable role name for user-bound identities; null for standalone API tokens."},"permissions":{"type":"array","description":"Granular workspace-wide permissions available through this token.","items":{"$ref":"#/components/schemas/AppPermission"}},"organization":{"$ref":"#/components/schemas/OrganizationMembership"},"organizations":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationMembership"}}}}}}},"401":{"description":"Missing or invalid token"}}}},"/organizations":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Organizations"],"summary":"List organizations available to the current identity","responses":{"200":{"description":"Memberships and the organization active for this request","content":{"application/json":{"schema":{"type":"object","required":["organizations","activeOrganizationId"],"properties":{"organizations":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationMembership"}},"activeOrganizationId":{"type":"string","format":"uuid"}}}}}},"401":{"description":"Missing or invalid authentication"}}},"post":{"tags":["Organizations"],"summary":"Create an organization for the current browser user","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":160}}}}}},"responses":{"201":{"description":"Organization created with the current user as admin","content":{"application/json":{"schema":{"type":"object","required":["organization"],"properties":{"organization":{"$ref":"#/components/schemas/OrganizationMembership"}}}}}},"403":{"description":"A browser session is required"},"422":{"description":"Invalid organization name"}}}},"/organizations/select":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Organizations"],"summary":"Select one of the current user's organizations","description":"Browser sessions persist the choice in an HTTP-only cookie. Native clients should send X-Organization-ID on subsequent requests.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["organizationId"],"properties":{"organizationId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Selected organization","content":{"application/json":{"schema":{"type":"object","required":["organization"],"properties":{"organization":{"$ref":"#/components/schemas/OrganizationMembership"}}}}}},"404":{"description":"Organization is not available to this identity"}}}},"/organizations/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Organizations"],"summary":"Rename an organization","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":160}}}}}},"responses":{"200":{"description":"Updated organization","content":{"application/json":{"schema":{"type":"object","required":["organization"],"properties":{"organization":{"$ref":"#/components/schemas/OrganizationMembership"}}}}}},"403":{"description":"Browser user lacks organization administration permission"},"404":{"description":"Organization not found or not available to this user"}}}},"/api/access/roles":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"servers":[{"url":"/"}],"get":{"tags":["Access control"],"summary":"List roles, inventory access rules, and permission metadata","description":"Requires an authenticated browser session with the roles.manage permission. Rules grant additional item-specific permissions when every condition matches.","security":[{"adminSession":[]}],"responses":{"200":{"description":"Roles, rules, and metadata used to administer granular access","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["roles","rules","permissionGroups","resourceRulePermissions"],"properties":{"roles":{"type":"array","items":{"$ref":"#/components/schemas/AccessRole"}},"rules":{"type":"array","items":{"$ref":"#/components/schemas/InventoryAccessRule"}},"permissionGroups":{"type":"array","items":{"$ref":"#/components/schemas/PermissionGroup"}},"resourceRulePermissions":{"type":"array","items":{"$ref":"#/components/schemas/InventoryRulePermission"}}}}}}},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"}}},"post":{"tags":["Access control"],"summary":"Create an access role","description":"Requires an authenticated browser session with the roles.manage permission. Role keys are stable identifiers used by users and conditional rules.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRoleInput"}}}},"responses":{"201":{"description":"Role created","content":{"application/json":{"schema":{"type":"object","required":["role"],"properties":{"role":{"$ref":"#/components/schemas/AccessRole"}}}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"409":{"description":"A role with the requested key already exists"},"422":{"description":"Invalid role"}}}},"/api/access/roles/{key}":{"servers":[{"url":"/"}],"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"key","in":"path","required":true,"description":"Stable role key.","schema":{"$ref":"#/components/schemas/AccessRoleKey"}}],"patch":{"tags":["Access control"],"summary":"Update an access role","description":"Requires an authenticated browser session with the roles.manage permission. Changing permissions revokes user-bound API tokens for members of this role. The built-in Admin role must retain every permission.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRolePatch"}}}},"responses":{"200":{"description":"Role updated","content":{"application/json":{"schema":{"type":"object","required":["role"],"properties":{"role":{"$ref":"#/components/schemas/AccessRole"}}}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"404":{"description":"Role not found"},"409":{"description":"The built-in Admin role would lose one or more permissions"},"422":{"description":"Invalid or empty role update"}}},"delete":{"tags":["Access control"],"summary":"Delete an access role","description":"Requires an authenticated browser session with the roles.manage permission. Built-in roles and roles assigned to users cannot be deleted; deleting a role also deletes its conditional inventory rules.","security":[{"adminSession":[]}],"responses":{"204":{"description":"Role and its conditional inventory rules deleted"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"404":{"description":"Role not found"},"409":{"description":"Built-in role or role still assigned to one or more users"}}}},"/api/access/rules":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"servers":[{"url":"/"}],"post":{"tags":["Access control"],"summary":"Create a conditional inventory access rule","description":"Requires an authenticated browser session with the roles.manage permission. The rule grants its permissions to members of the selected role only for inventory items that match every condition.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAccessRuleInput"}}}},"responses":{"201":{"description":"Inventory access rule created","content":{"application/json":{"schema":{"type":"object","required":["rule"],"properties":{"rule":{"$ref":"#/components/schemas/InventoryAccessRule"}}}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"422":{"description":"Invalid rule or selected role does not exist"}}}},"/api/access/rules/{id}":{"servers":[{"url":"/"}],"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"id","in":"path","required":true,"description":"Inventory access rule identifier.","schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Access control"],"summary":"Update a conditional inventory access rule","description":"Requires an authenticated browser session with the roles.manage permission. Changing a rule revokes user-bound API tokens for its previous and current roles.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAccessRulePatch"}}}},"responses":{"200":{"description":"Inventory access rule updated","content":{"application/json":{"schema":{"type":"object","required":["rule"],"properties":{"rule":{"$ref":"#/components/schemas/InventoryAccessRule"}}}}}},"400":{"description":"Invalid rule id or request body is not valid JSON"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"404":{"description":"Inventory access rule not found"},"422":{"description":"Invalid or empty inventory access rule update"}}},"delete":{"tags":["Access control"],"summary":"Delete a conditional inventory access rule","description":"Requires an authenticated browser session with the roles.manage permission. Deleting a rule revokes user-bound API tokens for its role.","security":[{"adminSession":[]}],"responses":{"204":{"description":"Inventory access rule deleted"},"400":{"description":"Invalid inventory access rule id"},"401":{"description":"Missing or invalid authenticated session"},"403":{"description":"A browser session with the roles.manage permission is required"},"404":{"description":"Inventory access rule not found"}}}},"/custom-fields":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Custom fields"],"summary":"List custom-field definitions","description":"Requires the read scope. Active definitions are returned by default, ordered by entity, position, and label.","parameters":[{"name":"entityType","in":"query","description":"Limit definitions to inventory items or serialized stock units.","schema":{"type":"string","enum":["inventory","stock_unit"]}},{"name":"includeArchived","in":"query","description":"Include soft-deleted definitions.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Matching custom-field definitions","content":{"application/json":{"schema":{"type":"object","required":["definitions"],"properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"},"422":{"description":"Invalid query parameters"}}},"post":{"tags":["Custom fields"],"summary":"Create a custom-field definition","description":"Requires an authenticated administrator session. Bearer tokens cannot create definitions. The key is generated from the label when omitted.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldDefinitionInput"}}}},"responses":{"201":{"description":"Custom-field definition created","content":{"application/json":{"schema":{"type":"object","required":["definition"],"properties":{"definition":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"409":{"description":"The generated or supplied key already exists in this entity scope"},"422":{"description":"Invalid custom-field definition"}}}},"/custom-fields/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/CustomFieldId"}],"get":{"tags":["Custom fields"],"summary":"Retrieve a custom-field definition","description":"Requires the read scope and can return either an active or archived definition.","responses":{"200":{"description":"Custom-field definition","content":{"application/json":{"schema":{"type":"object","required":["definition"],"properties":{"definition":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"},"404":{"description":"Custom-field definition not found"},"422":{"description":"Invalid definition id"}}},"patch":{"tags":["Custom fields"],"summary":"Update a custom-field definition","description":"Requires an authenticated administrator session. Entity scope and key are immutable. Send the last observed revision to prevent overwriting a concurrent edit; a successful edit increments it.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldDefinitionPatch"}}}},"responses":{"200":{"description":"Custom-field definition updated","content":{"application/json":{"schema":{"type":"object","required":["definition"],"properties":{"definition":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"404":{"description":"Custom-field definition not found"},"409":{"description":"Revision conflict; reload the definition before applying the update again","content":{"application/json":{"schema":{"type":"object","required":["error","details"],"properties":{"error":{"type":"string"},"details":{"type":"object","required":["currentRevision"],"properties":{"currentRevision":{"type":"integer","minimum":1}}}}}}}},"422":{"description":"Invalid or empty custom-field update"}}},"delete":{"tags":["Custom fields"],"summary":"Archive a custom-field definition","description":"Requires an authenticated administrator session. Soft deletion increments the definition revision and preserves existing values stored under its key.","security":[{"adminSession":[]}],"responses":{"204":{"description":"Definition archived"},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"404":{"description":"Custom-field definition not found"},"422":{"description":"Invalid definition id"}}}},"/custom-fields/{id}/options":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/CustomFieldId"}],"get":{"tags":["Custom fields"],"summary":"Search or resolve reference-field choices","description":"Requires the read scope. The definition must be an active reference field. Search results enforce its target type, category, and status filters; explicitly selected IDs are also resolved so previously saved values remain readable after filter changes.","parameters":[{"name":"q","in":"query","description":"Case-insensitive name, SKU, stock-unit code, or UUID search.","schema":{"type":"string","maxLength":120}},{"name":"selected","in":"query","description":"A saved target ID to resolve. Repeat for multiple IDs.","schema":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid"}},"style":"form","explode":true},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}}],"responses":{"200":{"description":"Matching and explicitly selected reference options","content":{"application/json":{"schema":{"type":"object","required":["options"],"properties":{"options":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldReferenceOption"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"},"404":{"description":"Custom-field definition not found"},"422":{"description":"Invalid query or the definition is not a reference field"}}}},"/label-setups":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Label setups"],"summary":"List reusable label setups","description":"Requires the read scope. Setups are ordered by name and contain the complete print layout.","responses":{"200":{"description":"Label setups","content":{"application/json":{"schema":{"type":"object","required":["labelSetups"],"properties":{"labelSetups":{"type":"array","items":{"$ref":"#/components/schemas/LabelSetup"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"}}},"post":{"tags":["Label setups"],"summary":"Create a label setup","description":"Requires the write scope. Setup names are unique case-insensitively.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelSetupInput"}}}},"responses":{"201":{"description":"Label setup created","content":{"application/json":{"schema":{"type":"object","required":["labelSetup"],"properties":{"labelSetup":{"$ref":"#/components/schemas/LabelSetup"}}}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the write scope"},"409":{"description":"A label setup with that name already exists"},"422":{"description":"Invalid label setup"}}}},"/label-setups/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"id","in":"path","required":true,"description":"Label setup identifier.","schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Label setups"],"summary":"Retrieve a label setup","description":"Requires the read scope.","responses":{"200":{"description":"Label setup","content":{"application/json":{"schema":{"type":"object","required":["labelSetup"],"properties":{"labelSetup":{"$ref":"#/components/schemas/LabelSetup"}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"},"404":{"description":"Label setup not found"},"422":{"description":"Invalid label setup id"}}},"patch":{"tags":["Label setups"],"summary":"Update a label setup using its current revision","description":"Requires the write scope. Send the last observed revision to prevent overwriting a concurrent edit; a successful update increments it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelSetupPatch"}}}},"responses":{"200":{"description":"Label setup updated","content":{"application/json":{"schema":{"type":"object","required":["labelSetup"],"properties":{"labelSetup":{"$ref":"#/components/schemas/LabelSetup"}}}}}},"400":{"description":"Request body is not valid JSON"},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the write scope"},"404":{"description":"Label setup not found"},"409":{"description":"Revision conflict or case-insensitive setup-name conflict"},"422":{"description":"Invalid or empty label setup update"}}},"delete":{"tags":["Label setups"],"summary":"Delete a label setup","description":"Requires the write scope and the last observed revision so a stale editor cannot delete newer work.","parameters":[{"name":"revision","in":"query","required":true,"description":"Current setup revision, preventing deletion from a stale editor.","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Label setup deleted"},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the write scope"},"404":{"description":"Label setup not found"},"409":{"description":"Setup revision changed; reload before deleting"},"422":{"description":"Invalid label setup id or revision"}}}},"/inventory-types":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Inventory structure"],"summary":"List configured inventory types","description":"Requires the read scope. Active definitions are returned in configured display order. Administrators may include archived definitions.","parameters":[{"name":"includeArchived","in":"query","description":"Include archived definitions when authenticated as an administrator.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Inventory type definitions","content":{"application/json":{"schema":{"type":"object","required":["types"],"properties":{"types":{"type":"array","items":{"$ref":"#/components/schemas/InventoryTypeDefinition"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"}}},"post":{"tags":["Inventory structure"],"summary":"Create an inventory type","description":"Requires an authenticated administrator browser session. Type keys are stable identifiers used by inventory records.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryTypeInput"}}}},"responses":{"201":{"description":"Inventory type created","content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"$ref":"#/components/schemas/InventoryTypeDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"409":{"description":"The type key already exists"},"422":{"description":"Invalid inventory type definition"}}}},"/inventory-types/{key}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"key","in":"path","required":true,"schema":{"$ref":"#/components/schemas/InventoryTypeKey"}}],"patch":{"tags":["Inventory structure"],"summary":"Update or restore an inventory type","description":"Requires an authenticated administrator browser session. The stable type key is immutable.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryTypePatch"}}}},"responses":{"200":{"description":"Inventory type updated","content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"$ref":"#/components/schemas/InventoryTypeDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"404":{"description":"Inventory type not found"},"409":{"description":"The fallback type cannot be archived"},"422":{"description":"Invalid or empty inventory type update"}}},"delete":{"tags":["Inventory structure"],"summary":"Archive an inventory type","description":"Requires an authenticated administrator browser session. Existing inventory records retain their type; the fallback type cannot be archived.","security":[{"adminSession":[]}],"responses":{"200":{"description":"Inventory type archived","content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"$ref":"#/components/schemas/InventoryTypeDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"404":{"description":"Inventory type not found"},"409":{"description":"The fallback type cannot be archived"},"422":{"description":"Invalid type key"}}}},"/relation-types":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Inventory structure"],"summary":"List configured relationship types","description":"Requires the read scope. Administrators may include archived definitions.","parameters":[{"name":"includeArchived","in":"query","description":"Include archived definitions when authenticated as an administrator.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Relationship type definitions","content":{"application/json":{"schema":{"type":"object","required":["relationTypes"],"properties":{"relationTypes":{"type":"array","items":{"$ref":"#/components/schemas/RelationTypeDefinition"}}}}}}},"401":{"description":"Missing or invalid session or bearer token"},"403":{"description":"Authenticated identity does not have the read scope"}}},"post":{"tags":["Inventory structure"],"summary":"Create a relationship type","description":"Requires an authenticated administrator browser session.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationTypeInput"}}}},"responses":{"201":{"description":"Relationship type created","content":{"application/json":{"schema":{"type":"object","required":["relationType"],"properties":{"relationType":{"$ref":"#/components/schemas/RelationTypeDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"409":{"description":"The relationship type key already exists"},"422":{"description":"Invalid relationship type definition"}}}},"/relation-types/{key}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"key","in":"path","required":true,"schema":{"$ref":"#/components/schemas/RelationTypeKey"}}],"patch":{"tags":["Inventory structure"],"summary":"Update, archive, or restore a relationship type","description":"Requires an authenticated administrator browser session. Built-in relationship types cannot be archived.","security":[{"adminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationTypePatch"}}}},"responses":{"200":{"description":"Relationship type updated","content":{"application/json":{"schema":{"type":"object","required":["relationType"],"properties":{"relationType":{"$ref":"#/components/schemas/RelationTypeDefinition"}}}}}},"401":{"description":"Missing or invalid administrator session"},"403":{"description":"A browser session with the admin role is required"},"404":{"description":"Relationship type not found"},"409":{"description":"A built-in relationship type cannot be archived"},"422":{"description":"Invalid or empty relationship type update"}}}},"/ai/recognize":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["AI"],"summary":"Match one photographed object to existing inventory items","description":"Requires direct inventory.read permission and the ai scope/ai.use permission. The uploaded image is transient and is not attached to an item. The server describes the dominant object, shortlists a bounded inventory catalog, and visually reranks up to five advisory matches. Clients must let the user review the result instead of treating it as an exact identifier.","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","additionalProperties":false,"required":["image"],"properties":{"image":{"type":"string","format":"binary","description":"Exactly one JPEG, PNG, WebP, AVIF, HEIC, or HEIF image."}}}}}},"responses":{"200":{"description":"Ranked, advisory inventory matches; matches may be empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryRecognitionResult"}}}},"202":{"description":"An identical idempotent request is still processing; retry with the same image and key after Retry-After."},"400":{"description":"Malformed idempotency key or multipart request"},"403":{"description":"Missing AI or direct inventory-read permission"},"409":{"description":"Idempotency-Key was reused for another identity or image"},"413":{"description":"Image exceeds the configured upload limit"},"415":{"description":"Request is not multipart or the image type is unsupported"},"422":{"description":"Missing","duplicate":null,"empty":null,"or unreadable image":null},"429":{"description":"AI recognition is disabled or the request limit was reached"},"502":{"description":"Vision provider or structured-output error"},"503":{"description":"Inventory catalog","retry protection":null,"or shared rate limiter unavailable":null}}}},"/ai/count":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["AI"],"summary":"Count matching physical items in one transient image","description":"Requires the ai scope. A selectable server-side Replicate model analyzes the image; text-aware models use itemHint as their query. The result is advisory and does not mutate stock. Supply a stable Idempotency-Key when retrying the same upload so a lost start response cannot create another paid prediction.","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["image"],"properties":{"image":{"type":"string","format":"binary","description":"One JPEG, PNG, WebP, AVIF, HEIC, or HEIF image."},"itemHint":{"type":"string","minLength":1,"maxLength":240,"description":"Optional description of the object that should be counted."},"itemId":{"type":"string","format":"uuid","description":"Optional inventory item identifier used to scope idempotent retries."},"modelId":{"type":"string","enum":["grounding-dino","yolo-world","sam-2","sam-3"],"description":"Optional counting model. The server default is used when omitted."}}}}}},"responses":{"200":{"description":"Advisory visual count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCount"}}}},"202":{"description":"The Replicate prediction was created and is warming or processing; poll it with the signed jobToken.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCountJob"}}}},"400":{"description":"Missing or malformed Idempotency-Key","or malformed multipart request":null},"409":{"description":"The same idempotent start is still being persisted, or Replicate may have accepted it without returning a job ID. Retry only with the same image and Idempotency-Key after Retry-After; the server keeps the attempt reserved long enough to prevent an overlapping paid prediction.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}},"413":{"description":"Image exceeds the configured upload limit"},"415":{"description":"Request is not multipart or the image type is unsupported"},"422":{"description":"Invalid image","item hint":null,"model":null,"or provider detection limit":null},"429":{"description":"AI request limit reached","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}},"502":{"description":"Replicate prediction creation or result-validation error"},"503":{"description":"Replicate configuration","billing":null,"authentication":null,"capacity":null,"or shared rate limiter unavailable":null},"504":{"description":"Replicate prediction exceeded the configured deadline"}}}},"/ai/count/jobs":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["AI"],"summary":"Poll one signed Replicate count job","description":"Requires the ai scope and the same authenticated identity that created the job. Polling checks the existing prediction and does not start or bill another prediction.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["jobToken"],"properties":{"jobToken":{"type":"string","minLength":1,"maxLength":4096}}}}}},"responses":{"200":{"description":"Completed advisory visual count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCount"}}}},"202":{"description":"Prediction is still processing","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCountJob"}}}},"401":{"description":"Missing or invalid identity"},"403":{"description":"Identity is missing the ai scope"},"422":{"description":"Invalid","expired":null,"or wrong-identity job token":null},"502":{"description":"Replicate polling or result-validation error. terminal=true means the prediction itself has finished and a new count may be started; terminal=false means the same signed job should be resumed.","content":{"application/json":{"schema":{"type":"object","required":["error","terminal"],"properties":{"error":{"type":"string"},"terminal":{"type":"boolean"}}}}}},"503":{"description":"Replicate authentication/configuration error","or a transient capacity/poll timeout marked with Retry-After":null},"504":{"description":"Prediction exceeded its deadline"}}}},"/ai/count-models":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["AI"],"summary":"List Replicate counting models enabled for this deployment","description":"Requires the ai scope. The same catalog is consumed by the web app and iOS app.","responses":{"200":{"description":"Available counting models and the deployment default","content":{"application/json":{"schema":{"type":"object","required":["models","defaultModelId"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/InventoryCountModel"}},"defaultModelId":{"type":"string","enum":["grounding-dino","yolo-world","sam-2","sam-3"]}}}}}},"401":{"description":"Missing or invalid token"},"403":{"description":"Token is missing the ai scope"}}}},"/ai/image-models":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["AI"],"summary":"List image-generation models enabled for this deployment","description":"Requires the ai scope. Only allowlisted models with configured provider credentials are returned.","responses":{"200":{"description":"Available image-generation models and the deployment default","content":{"application/json":{"schema":{"type":"object","required":["models","defaultModelId"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ImageGenerationModel"}},"defaultModelId":{"type":["string","null"]}}}}}},"401":{"description":"Missing or invalid token"},"403":{"description":"Token is missing the ai scope"}}}},"/languages":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Content translations"],"summary":"List active content languages","responses":{"200":{"description":"Canonical and target languages"}}},"post":{"tags":["Content translations"],"summary":"Add a content language","description":"Requires an administrator browser session. The first language becomes the canonical default.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","label"],"properties":{"code":{"type":"string","minLength":2,"maxLength":35,"examples":["de"]},"label":{"type":"string","minLength":1,"maxLength":120,"examples":["German"]},"isDefault":{"type":"boolean","default":false},"autoTranslate":{"type":"boolean","default":true},"instructions":{"type":"string","maxLength":5000},"position":{"type":"integer","minimum":0,"maximum":100000}}}}}},"responses":{"201":{"description":"Language added"},"409":{"description":"Duplicate code or unsafe default-language change"},"422":{"description":"Invalid language"}}}},"/languages/{code}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"code","in":"path","required":true,"schema":{"type":"string","maxLength":35}}],"patch":{"tags":["Content translations"],"summary":"Update a content language","description":"Requires an administrator browser session. The canonical default cannot change after translations exist.","responses":{"200":{"description":"Language updated"},"404":{"description":"Language not found"},"409":{"description":"Unsafe default-language change"}}},"delete":{"tags":["Content translations"],"summary":"Archive a target content language","description":"Requires an administrator browser session. Saved translations are retained.","responses":{"200":{"description":"Language archived"},"409":{"description":"The default language cannot be archived"}}}},"/translations/regenerate":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Content translations","AI"],"summary":"Queue a durable translation backfill","description":"Requires an administrator browser session. All selected resource-locale jobs are persisted before the response; processing continues in the background.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"languageCodes":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":35}},"force":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"No target-language jobs were needed"},"202":{"description":"Durable translation jobs queued"}}}},"/resources":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Resources"],"summary":"List inventory items","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"$ref":"#/components/schemas/InventoryTypeKey"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"language","in":"query","description":"Active BCP 47 content locale. Missing or stale fields fall back individually to canonical content.","schema":{"type":"string","maxLength":35}}],"responses":{"200":{"description":"Paginated inventory","content":{"application/json":{"schema":{"type":"object","properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/Resource"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}}}},"post":{"tags":["Resources"],"summary":"Create an inventory item","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceInput"}}}},"responses":{"200":{"description":"Replayed the original creation response"},"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"409":{"description":"Idempotency key was used with a different request"}}}},"/resources/import":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Data exchange"],"summary":"Import inventory items from UTF-8 CSV","description":"Creates up to 1,000 items from a raw CSV body of at most 5 MB. Rows are validated independently, existing items are never overwritten, and structured fields may contain JSON. The same Idempotency-Key and identical file can be retried safely.","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"text/csv":{"schema":{"type":"string","format":"binary","description":"UTF-8 CSV with a required name header. See CsvImportResponse for row-level outcomes."}},"application/csv":{"schema":{"type":"string","format":"binary"}},"application/vnd.ms-excel":{"schema":{"type":"string","format":"binary"}},"text/plain":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Every row replayed from an earlier identical import","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}}},"201":{"description":"Import completed without row errors and at least one row was created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}}},"207":{"description":"Import completed with one or more row-level errors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}}},"400":{"description":"Missing or invalid Idempotency-Key, malformed CSV, or invalid UTF-8"},"413":{"description":"File exceeds 5 MB or contains more than 1,000 data rows"},"415":{"description":"Unsupported media type"},"422":{"description":"Missing rows or invalid CSV headers"}}}},"/resources/export":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Data exchange"],"summary":"Export the complete inventory as CSV, Excel, or PDF","description":"Returns up to 100,000 inventory records. CSV remains the default and is BOM-prefixed with potential spreadsheet formulas escaped. Excel includes formatted, filterable inventory and variant sheets; PDF is a compact printable report.","parameters":[{"in":"query","name":"format","schema":{"type":"string","enum":["csv","xlsx","pdf"],"default":"csv"},"description":"Download format. Omitting the parameter preserves the existing CSV response."},{"in":"query","name":"lang","schema":{"type":"string","enum":["en","de"],"default":"en"},"description":"Report language used for generated Excel and PDF labels."}],"responses":{"200":{"description":"Inventory export in the requested format","headers":{"Content-Disposition":{"schema":{"type":"string"},"description":"Dated inventory filename with an extension matching the requested format."}},"content":{"text/csv":{"schema":{"type":"string"}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}},"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Unsupported export format"},"413":{"description":"The workspace contains more than 100,000 records"}}}},"/resources/batch":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"patch":{"tags":["Resources"],"summary":"Apply shared fields and additional tags to multiple inventory items atomically","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid"}},"changes":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"status":{"type":"string","enum":["available","in-use","maintenance","archived"]},"location":{"type":["string","null"],"maxLength":240},"priority":{"type":"integer","minimum":1,"maximum":5}}},"addTags":{"type":"array","maxItems":40,"items":{"type":"string","minLength":1,"maxLength":60}}}}}}},"responses":{"200":{"description":"Selected inventory items updated"},"404":{"description":"At least one selected inventory item no longer exists"},"422":{"description":"Invalid or empty batch update"}}}},"/resources/{id}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Resources"],"summary":"Retrieve an inventory item","parameters":[{"name":"language","in":"query","description":"Enabled BCP 47 content language. Missing or stale translated fields fall back to canonical content.","schema":{"type":"string","maxLength":35,"examples":["de"]}}],"responses":{"200":{"description":"Inventory item","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Resources"],"summary":"Update an inventory item","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourcePatch"}}}},"responses":{"200":{"description":"Updated"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Resources"],"summary":"Delete an inventory item and its local media","responses":{"204":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/resources/{id}/variants":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Resources","Stock"],"summary":"List optional bulk-stock variants for an inventory item","responses":{"200":{"description":"Variants and the allocated/unallocated parent stock summary","content":{"application/json":{"schema":{"type":"object","required":["variants","summary","trackingMode"],"properties":{"variants":{"type":"array","items":{"$ref":"#/components/schemas/ResourceVariant"}},"summary":{"$ref":"#/components/schemas/ResourceVariantStockSummary"},"trackingMode":{"type":"string","enum":["bulk","serialized"]}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Resources","Stock"],"summary":"Add a variant and optionally allocate existing parent stock","description":"Variants are bulk-only. `initialAllocation` moves existing unallocated parent stock into the variant without changing the parent total.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceVariantInput"}}}},"responses":{"201":{"description":"Variant created"},"409":{"description":"Identifier conflict","serialized tracking":null,"or insufficient unallocated stock":null},"422":{"description":"Invalid variant"}}}},"/resources/{id}/variants/{variantId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Resources"],"summary":"Update variant identity or price fields","description":"Quantity cannot be patched; use a dated variant stock movement.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceVariantPatch"}}}},"responses":{"200":{"description":"Variant updated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"SKU or barcode is already used"}}},"delete":{"tags":["Resources"],"summary":"Delete an unused zero-stock variant","responses":{"204":{"description":"Variant deleted"},"409":{"description":"Variant has stock or movement history"}}}},"/resources/{id}/variants/{variantId}/stock/movements":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Stock"],"summary":"Book an atomic parent and variant stock movement","description":"The signed delta updates parent and variant quantities together and appends one dated stock-ledger row.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceVariantStockMovementInput"}}}},"responses":{"201":{"description":"Parent and variant stock updated atomically"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Insufficient stock","serialized tracking":null,"or maximum quantity exceeded":null},"422":{"description":"Invalid stock movement"}}}},"/resources/{id}/translations":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Content translations"],"summary":"Inspect field-level translation freshness","responses":{"200":{"description":"Per-language current","stale":null,"and missing fields":null},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Content translations","AI"],"summary":"Queue stale fields for background translation","description":"Requires ai scope. Omit languageCodes to queue every active target language. Jobs are coalesced per resource and locale and survive restarts.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"languageCodes":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":35}},"force":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"No target-language jobs were needed"},"202":{"description":"Durable translation jobs queued"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid or inactive target language"}}}},"/resources/{id}/translations/{languageCode}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"},{"name":"languageCode","in":"path","required":true,"schema":{"type":"string","maxLength":35}}],"patch":{"tags":["Content translations"],"summary":"Edit, approve, or unlock translated fields","description":"Requires write scope and the current locale-document revision. Human edits are protected from AI overwrite; accepting a suggestion keeps the field human-managed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["expectedRevision","operations"],"properties":{"expectedRevision":{"type":"integer","minimum":0},"operations":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","required":["action","fieldKey"],"properties":{"action":{"type":"string","enum":["set","accept_suggestion","use_ai"]},"fieldKey":{"type":"string","maxLength":96},"translatedText":{"type":"string","maxLength":100000}}}}}}}}},"responses":{"200":{"description":"Translation document updated"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Translation revision changed or suggestion became stale"},"422":{"description":"Invalid language","field":null,"or operation":null}}}},"/resources/{id}/relations":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Inventory structure"],"summary":"List relationships touching an inventory item","description":"Returns incoming and outgoing directed relationships with both endpoint summaries and the relationship definition.","responses":{"200":{"description":"Resource relationships","content":{"application/json":{"schema":{"type":"object","required":["relations"],"properties":{"relations":{"type":"array","items":{"$ref":"#/components/schemas/ResourceRelation"}}}}}}},"422":{"description":"Invalid resource id"}}},"post":{"tags":["Inventory structure"],"summary":"Create or pin a manual relationship","description":"One endpoint must match the resource id in the path. Containment relationships reject invalid parents, self-reference, and direct or indirect cycles. Creating an existing spatial relationship converts it to a manual relationship.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceRelationInput"}}}},"responses":{"201":{"description":"Manual relationship created or pinned","content":{"application/json":{"schema":{"type":"object","required":["relation"],"properties":{"relation":{"$ref":"#/components/schemas/ResourceRelationRecord"}}}}}},"404":{"description":"One of the inventory items or the relationship type was not found"},"409":{"description":"The containment relationship would create a cycle"},"422":{"description":"Invalid relationship or a relationship type that disallows manual use"}}}},"/relations/{relationId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"relationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"delete":{"tags":["Inventory structure"],"summary":"Remove a manual resource relationship","description":"Spatially derived relationships cannot be deleted directly. After deletion, spatial containment is recalculated.","parameters":[{"name":"resourceId","in":"query","required":true,"description":"One endpoint of the relationship, used to scope the deletion.","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Manual relationship removed"},"404":{"description":"Manual relationship not found"},"422":{"description":"Invalid relationship or resource id"}}}},"/resources/lookup":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Resources"],"summary":"Resolve a scanned QR or barcode to an inventory item","description":"Accepts an item UUID, Inventory resource URL, item or variant SKU/barcode, or serial number. Variant matches include a `variant` object.","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":2048}}],"responses":{"200":{"description":"Matching inventory item","content":{"application/json":{"schema":{"type":"object","required":["resource","matchedBy"],"properties":{"resource":{"$ref":"#/components/schemas/Resource"},"variant":{"$ref":"#/components/schemas/ResourceVariant"},"matchedBy":{"type":"string","enum":["id","sku","barcode","serialNumber","variantSku","variantBarcode"]}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Serial number is ambiguous"}}}},"/stock":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Stock"],"summary":"Retrieve stock health and replenishment forecasts","responses":{"200":{"description":"Stock overview","content":{"application/json":{"schema":{"type":"object","required":["summary","items"],"properties":{"summary":{"type":"object","properties":{"trackedItems":{"type":"integer"},"totalQuantity":{"type":"integer"},"totalOnOrder":{"type":"integer"},"incomingItems":{"type":"integer"},"lowStockItems":{"type":"integer"},"outOfStockItems":{"type":"integer"},"predictedStockouts":{"type":"integer"},"reorderItems":{"type":"integer"}}},"items":{"type":"array","items":{"$ref":"#/components/schemas/StockOverviewItem"}}}}}}}}}},"/stock/scan-workflows":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Scan workflows"],"summary":"List configurable stock scan workflows","responses":{"200":{"description":"Scan workflows","content":{"application/json":{"schema":{"type":"object","required":["workflows"],"properties":{"workflows":{"type":"array","items":{"$ref":"#/components/schemas/ScanWorkflow"}}}}}}}}},"post":{"tags":["Scan workflows"],"summary":"Create a stock scan workflow","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanWorkflowInput"}}}},"responses":{"201":{"description":"Workflow created","content":{"application/json":{"schema":{"type":"object","required":["workflow"],"properties":{"workflow":{"$ref":"#/components/schemas/ScanWorkflow"}}}}}},"409":{"description":"The target item does not use serialized tracking"},"422":{"description":"Invalid workflow definition"}}}},"/stock/scan-workflows/{workflowId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Scan workflows"],"summary":"Retrieve one stock scan workflow","responses":{"200":{"description":"Scan workflow","content":{"application/json":{"schema":{"type":"object","required":["workflow"],"properties":{"workflow":{"$ref":"#/components/schemas/ScanWorkflow"}}}}}},"404":{"description":"Workflow not found"}}},"patch":{"tags":["Scan workflows"],"summary":"Update a workflow using its current revision","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanWorkflowPatch"}}}},"responses":{"200":{"description":"Workflow updated","content":{"application/json":{"schema":{"type":"object","required":["workflow"],"properties":{"workflow":{"$ref":"#/components/schemas/ScanWorkflow"}}}}}},"404":{"description":"Workflow not found"},"409":{"description":"Revision conflict or incompatible target item"},"422":{"description":"Invalid workflow update"}}},"delete":{"tags":["Scan workflows"],"summary":"Delete a stock scan workflow","parameters":[{"name":"revision","in":"query","required":true,"description":"Current workflow revision, preventing deletion from a stale editor.","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Workflow deleted; immutable scan audit rows are preserved"},"404":{"description":"Workflow not found"},"409":{"description":"Workflow revision changed; reload before deleting"},"422":{"description":"The workflow id or required single positive revision is invalid"}}}},"/stock/scans/resolve":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Scan workflows"],"summary":"Resolve and preview a scanned code without changing stock","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workflowId","code"],"additionalProperties":false,"properties":{"workflowId":{"type":"string","format":"uuid"},"code":{"type":"string","minLength":1,"maxLength":2048}}}}}},"responses":{"200":{"description":"Reviewed scan target and required operator inputs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockScanResolution"}}}},"404":{"description":"Workflow not found"},"409":{"description":"Workflow disabled or target is not serialized"},"422":{"description":"Invalid request or the code does not match the configured extractor"}}}},"/stock/scans/execute":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["Scan workflows"],"summary":"Atomically apply a previously reviewed stock scan","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockScanExecutionInput"}}}},"responses":{"200":{"description":"Replayed the original scan execution response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockScanExecution"}}}},"201":{"description":"Unit, stock ledger, and immutable scan audit updated atomically","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockScanExecution"}}}},"400":{"description":"Missing or invalid Idempotency-Key"},"404":{"description":"Workflow or target unit not found"},"409":{"description":"Revision, stale resource or unit preview, idempotency, tracking-mode, or stock conflict"},"422":{"description":"Invalid code or operator input"}}}},"/resources/{id}/stock":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Stock"],"summary":"Retrieve one item's stock policy, forecast, units, and ledger","responses":{"200":{"description":"Complete stock detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDetail"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/resources/{id}/stock/locations":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Stock"],"summary":"Retrieve stock balances by structured inventory location","description":"Bulk balances are derived from location-aware movements; serialized balances count available units at each location. The response also lists active inventory records whose types can contain stock.","responses":{"200":{"description":"Per-location stock breakdown and selectable locations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockLocationsResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid resource id"}}}},"/inventory-counts/due":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Inventory cycles"],"summary":"List inventory cycles that are currently due","responses":{"200":{"description":"Due inventory counts ordered by due date","content":{"application/json":{"schema":{"type":"object","required":["due"],"properties":{"due":{"type":"array","items":{"$ref":"#/components/schemas/DueInventoryCycle"}}}}}}}}}},"/resources/{id}/inventory-cycle":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Inventory cycles"],"summary":"Retrieve an item's inventory cycle and recent count history","responses":{"200":{"description":"Inventory cycle, nullable policy, and up to 25 recent counts","content":{"application/json":{"schema":{"type":"object","required":["cycle"],"properties":{"cycle":{"$ref":"#/components/schemas/InventoryCycle"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid resource id"}}},"put":{"tags":["Inventory cycles"],"summary":"Create or replace an item's recurring count policy","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCyclePolicyInput"}}}},"responses":{"200":{"description":"Inventory cycle policy saved","content":{"application/json":{"schema":{"type":"object","required":["policy"],"properties":{"policy":{"$ref":"#/components/schemas/InventoryCyclePolicy"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid resource id or count interval"}}}},"/resources/{id}/inventory-counts":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Inventory cycles"],"summary":"List an item's recent inventory counts","responses":{"200":{"description":"Up to 25 recent counts","content":{"application/json":{"schema":{"type":"object","required":["counts"],"properties":{"counts":{"type":"array","items":{"$ref":"#/components/schemas/InventoryCountRecord"}}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid resource id"}}},"post":{"tags":["Inventory cycles"],"summary":"Record an inventory count or serialized-unit review","description":"Bulk counts reconcile either the global balance or one structured location. Serialized items are reviewed through their individual units and may complete the cycle when the submitted whole-item count matches current serialized availability. Every completion appends an inventory-count movement and advances an existing cycle policy.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCountInput"}}}},"responses":{"200":{"description":"Replayed an earlier count with the same Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCountMutation"}}}},"201":{"description":"Count recorded and stock reconciled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryCountMutation"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Serialized count differs from current unit availability, conflicting idempotency key, or an invalid global count below assigned location stock"},"422":{"description":"Invalid count or structured location"}}}},"/resources/{id}/assignments":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Assignments"],"summary":"List checkout, assignment, and reservation records for an item","responses":{"200":{"description":"Assignment history, current availability, and selectable serialized units","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentList"}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Invalid resource id"}}},"post":{"tags":["Assignments"],"summary":"Check out, assign, or reserve inventory","description":"Atomically creates an active allocation, reduces available stock, updates a serialized unit when selected, and appends a stock movement.","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentInput"}}}},"responses":{"200":{"description":"Replayed the original assignment response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentMutation"}}}},"201":{"description":"Assignment created and stock allocated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentMutation"}}}},"400":{"description":"Missing or invalid Idempotency-Key"},"404":{"description":"Inventory item or serialized unit not found"},"409":{"description":"Insufficient stock, unavailable unit, or conflicting idempotency key"},"422":{"description":"Invalid recipient, quantity, dates, or tracking-mode combination"}}}},"/assignments/{assignmentId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"assignmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Assignments"],"summary":"Return or cancel an active assignment","description":"Atomically completes the assignment, restores stock when applicable, restores an assigned serialized unit to available, and appends a stock movement.","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentCompletion"}}}},"responses":{"200":{"description":"Assignment completed or an identical completion replayed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAssignmentMutation"}}}},"400":{"description":"Missing or invalid Idempotency-Key"},"404":{"description":"Assignment, inventory item, or serialized unit not found"},"409":{"description":"Assignment already completed, stock overflow, or conflicting idempotency key"},"422":{"description":"Invalid status or completion date"}}}},"/resources/{id}/stock/config":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"patch":{"tags":["Stock"],"summary":"Update tracking mode and replenishment policy","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockConfigInput"}}}},"responses":{"200":{"description":"Updated stock policy"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Tracking mode transition would break serialized-unit integrity"}}}},"/resources/{id}/bom":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Manufacturing"],"summary":"Retrieve an item's bill of materials and current build capacity","responses":{"200":{"description":"Bill of materials with component availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BomDetail"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Manufacturing"],"summary":"Replace an item's complete bill of materials","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["components"],"properties":{"components":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/BomComponentInput"}}}}}}},"responses":{"200":{"description":"Bill of materials replaced"},"409":{"description":"Circular dependency or concurrent referenced-resource conflict"},"422":{"description":"Invalid, duplicate, missing, or self-referencing component list"}}}},"/resources/{id}/stock/builds":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Manufacturing"],"summary":"List completed assembly builds for an item","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Completed builds with immutable component snapshots","content":{"application/json":{"schema":{"type":"object","required":["builds"],"properties":{"builds":{"type":"array","items":{"$ref":"#/components/schemas/AssemblyBuild"}}}}}}}}},"post":{"tags":["Manufacturing"],"summary":"Atomically consume components and create finished stock","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssemblyBuildInput"}}}},"responses":{"200":{"description":"Replayed the original assembly build"},"201":{"description":"Components consumed and finished stock created atomically"},"400":{"description":"Missing or invalid Idempotency-Key"},"409":{"description":"Component shortage, serialized-unit, or idempotency conflict"},"422":{"description":"Invalid build request"}}}},"/resources/{id}/stock/movements":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Stock"],"summary":"List the immutable dated stock ledger","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":100}},{"name":"before","in":"query","description":"Return movements that occurred before this timestamp.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Stock movements","content":{"application/json":{"schema":{"type":"object","required":["movements"],"properties":{"movements":{"type":"array","items":{"$ref":"#/components/schemas/StockMovement"}}}}}}}}},"post":{"tags":["Stock"],"summary":"Book a bulk stock change or structured location transfer","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockMovementInput"}}}},"responses":{"200":{"description":"Replayed the original stock movement response"},"201":{"description":"Movement booked and balance updated"},"409":{"description":"Insufficient stock, serialized mode, or conflicting idempotency key"},"422":{"description":"Invalid quantity, movement direction, or structured location transfer"}}}},"/resources/{id}/stock/units":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"get":{"tags":["Stock"],"summary":"List individually identified stock units","responses":{"200":{"description":"Serialized units","content":{"application/json":{"schema":{"type":"object","required":["units"],"properties":{"units":{"type":"array","items":{"$ref":"#/components/schemas/StockUnit"}}}}}}}}},"post":{"tags":["Stock"],"summary":"Create one or more individually identified stock units","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockUnitInput"}}}},"responses":{"201":{"description":"Units created with audit entries"},"409":{"description":"Duplicate code or incompatible tracking mode"}}}},"/resources/{id}/stock/units/{unitId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"},{"name":"unitId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["Stock"],"summary":"Change a unit's status, location, or metadata with an audit entry","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockUnitPatch"}}}},"responses":{"200":{"description":"Unit updated and movement recorded"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/purchase-orders":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Purchasing"],"summary":"List purchase orders and their open incoming quantities","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["draft","ordered","partially-received","received","cancelled"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":100}}],"responses":{"200":{"description":"Purchase orders","content":{"application/json":{"schema":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrder"}}}}}}}}},"post":{"tags":["Purchasing"],"summary":"Create a draft or ordered purchase order","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderInput"}}}},"responses":{"200":{"description":"Replayed the original purchase-order response"},"201":{"description":"Purchase order created"},"400":{"description":"Missing or invalid Idempotency-Key"},"409":{"description":"Idempotency conflict or supported open-order total exceeded"},"422":{"description":"Invalid purchase order, duplicate line, or missing inventory item"}}}},"/purchase-orders/{orderId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"orderId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Purchasing"],"summary":"Retrieve one purchase order","responses":{"200":{"description":"Purchase order","content":{"application/json":{"schema":{"type":"object","required":["order"],"properties":{"order":{"$ref":"#/components/schemas/PurchaseOrder"}}}}}},"404":{"description":"Purchase order not found"}}},"patch":{"tags":["Purchasing"],"summary":"Update or cancel a purchase order","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"type":["string","null"],"maxLength":160},"supplier":{"type":"string","maxLength":240},"status":{"type":"string","enum":["draft","ordered","cancelled"]},"orderedAt":{"type":"string","format":"date-time"},"expectedAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string","maxLength":20000}}}}}},"responses":{"200":{"description":"Purchase order updated"},"409":{"description":"Invalid lifecycle transition"}}}},"/purchase-orders/{orderId}/lines/{lineId}/receipts":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"name":"orderId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"lineId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Purchasing"],"summary":"Receive all or part of an ordered line into physical stock","parameters":[{"$ref":"#/components/parameters/RequiredIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseReceiptInput"}}}},"responses":{"200":{"description":"Replayed the original goods receipt"},"201":{"description":"Receipt and physical stock movements created atomically"},"400":{"description":"Missing or invalid Idempotency-Key"},"409":{"description":"Over-receipt, order-state, serialized-unit, or idempotency conflict"}}}},"/resources/{id}/media":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"},{"$ref":"#/components/parameters/ResourceId"}],"post":{"tags":["Media"],"summary":"Upload up to 12 media files, including Apple USDZ object models","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"files":{"type":"array","maxItems":12,"description":"Images, videos, PDF documents, or .usdz models sent as model/vnd.usdz+zip.","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Replayed the existing upload batch"},"201":{"description":"Uploaded"},"409":{"description":"Idempotency key belongs to another resource"},"413":{"description":"A file exceeds MAX_UPLOAD_MB","or a USDZ model exceeds MAX_USDZ_UPLOAD_MB":null},"415":{"description":"Unsupported media type","invalid USDZ filename":null,"or structurally invalid USDZ package":null},"422":{"description":"A USDZ Object Capture model was uploaded without an existing or accompanying item image"},"503":{"description":"The configured storage provider cannot store the accepted media type"}}},"patch":{"tags":["Media"],"summary":"Reorder all media","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["order"],"properties":{"order":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"responses":{"200":{"description":"Reordered"}}}},"/resources/{id}/media/{mediaId}":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"delete":{"tags":["Media"],"summary":"Remove one media file","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"name":"mediaId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Removed"}}}},"/resources/{id}/analyze":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["AI"],"summary":"Generate structured item fields from the first three images","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"overwrite":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Item enriched or completed response replayed"},"202":{"description":"An operation with this key is still processing"},"409":{"description":"Idempotency key belongs to another resource or payload"},"429":{"description":"AI request limit reached","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}},"502":{"description":"AI provider error"},"503":{"description":"Shared AI rate limiter unavailable"}}}},"/resources/{id}/cover":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"post":{"tags":["AI"],"summary":"Generate a square studio or transparent cover from an item image","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"sourceMediaId":{"type":"string","format":"uuid","description":"Image to use as the visual reference. Defaults to the first non-AI image, then falls back to the first image."},"prompt":{"type":"string","maxLength":5000},"modelId":{"type":"string","maxLength":240,"description":"An ID returned by GET /ai/image-models. Omit it to use the deployment default."},"transparentBackground":{"type":"boolean","default":false,"description":"When true, store a transparent PNG instead of an opaque JPEG."},"transparencyMethod":{"type":"string","enum":["greenscreen","difference-matting"],"default":"difference-matting","description":"Greenscreen uses one generated chroma-key pass. Difference matting uses aligned white and black passes for higher-quality alpha, including translucent details and soft shadows."}}}}}},"responses":{"200":{"description":"Cover generated or completed response replayed"},"202":{"description":"An operation with this key is still processing"},"409":{"description":"Idempotency key belongs to another resource or payload"},"422":{"description":"Invalid request or unavailable image model"},"429":{"description":"Image generation limit reached","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}},"502":{"description":"AI provider error"},"503":{"description":"Shared AI rate limiter unavailable"}}}},"/stats":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Insights"],"summary":"Retrieve aggregate dashboard statistics","responses":{"200":{"description":"Statistics"}}}},"/duplicates":{"parameters":[{"$ref":"#/components/parameters/OrganizationId"}],"get":{"tags":["Insights"],"summary":"Find likely duplicate item pairs","responses":{"200":{"description":"Ranked duplicate pairs"}}},"post":{"tags":["Insights"],"summary":"Merge one duplicate into another","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["keepResourceId","removeResourceId"],"properties":{"keepResourceId":{"type":"string","format":"uuid"},"removeResourceId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Merged resource"}}}}},"webhooks":{"inventoryEvent":{"post":{"tags":["Webhooks"],"summary":"Receive an outgoing Inventory event","security":[],"description":"This operation documents the HTTP request Inventory sends to each subscribed target; it is not an endpoint hosted by Inventory. Delivery is at least once, so receivers must deduplicate by the stable event id. Return any 2xx status to acknowledge the exact request body.","parameters":[{"name":"X-Inventory-Event-Id","in":"header","required":true,"description":"Stable event UUID; use it as the receiver's deduplication key.","schema":{"type":"string","format":"uuid"}},{"name":"X-Inventory-Event-Type","in":"header","required":true,"description":"Event name, also present in the JSON envelope.","schema":{"$ref":"#/components/schemas/WebhookOutboundEventType"}},{"name":"X-Inventory-Delivery-Id","in":"header","required":true,"description":"UUID of this endpoint-specific delivery record.","schema":{"type":"string","format":"uuid"}},{"name":"X-Inventory-Timestamp","in":"header","required":true,"description":"Unix timestamp also carried as `t` in the signature header.","schema":{"type":"string","pattern":"^[0-9]+$"}},{"name":"X-Inventory-Signature","in":"header","required":true,"description":"`t=<unix>,v1=<hex>` where `v1` is the lowercase hexadecimal HMAC-SHA256 of `<unix>.<exact raw request body>` using the endpoint signing secret. Verify the raw bytes before parsing JSON.","schema":{"type":"string","pattern":"^t=[0-9]+,v1=[a-f0-9]{64}$"},"example":"t=1786608000,v1=7d6f2dba7b8d83cd0c87bfce4c34f35621e96fe930a29d309926f7156bdb976c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Event acknowledged; Inventory marks the delivery successful."},"default":{"description":"Non-2xx response; transient statuses may be retried according to the delivery policy."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"inv_ token"},"adminSession":{"type":"apiKey","in":"cookie","name":"authjs.session-token","description":"Auth.js browser session cookie; each operation declares its required administrative permission. HTTPS deployments use the secure-prefixed cookie variant."},"cronSecret":{"type":"http","scheme":"bearer","bearerFormat":"NOTIFICATION_CRON_SECRET","description":"Deployment-level scheduler secret used only by the notification run endpoint."},"webhookCronSecret":{"type":"http","scheme":"bearer","bearerFormat":"WEBHOOK_CRON_SECRET","description":"Deployment-level scheduler secret used only by the outgoing webhook run endpoint."}},"parameters":{"OrganizationId":{"name":"X-Organization-ID","in":"header","required":false,"description":"Organization membership selected for this request. User-bound credentials may select any active membership; standalone tokens may only repeat their pinned organization ID.","schema":{"type":"string","format":"uuid"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"UUID identifying one queue operation; safe to reuse for retries.","schema":{"type":"string","format":"uuid"}},"RequiredIdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"UUID identifying this atomic operation; reuse it only to retry the exact same request.","schema":{"type":"string","format":"uuid"}},"ResourceId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"CustomFieldId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"WebhookId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"WebhookDeliveryId":{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}},"responses":{"NotFound":{"description":"Resource not found"}},"schemas":{"OrganizationMembership":{"type":"object","additionalProperties":false,"required":["id","name","slug","role","roleName"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":160},"slug":{"type":"string","minLength":1,"maxLength":180},"role":{"type":["string","null"],"pattern":"^[a-z][a-z0-9_-]{0,63}$"},"roleName":{"type":["string","null"]},"canManage":{"type":"boolean","description":"Present on organization-list responses; true when the current identity can administer that active organization."}}},"NotificationEventType":{"type":"string","enum":["low_stock","expiry","maintenance","return_due"]},"Notification":{"type":"object","required":["id","eventType","sourceKey","title","body","metadata","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"eventType":{"$ref":"#/components/schemas/NotificationEventType"},"resourceId":{"type":["string","null"],"format":"uuid"},"assignmentId":{"type":["string","null"],"format":"uuid"},"sourceKey":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"href":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"readAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}},"NotificationPreferencePatch":{"type":"object","additionalProperties":false,"properties":{"enabledEventTypes":{"type":"array","uniqueItems":true,"maxItems":4,"items":{"$ref":"#/components/schemas/NotificationEventType"}},"frequency":{"type":"string","enum":["daily","immediate"]},"digestHour":{"type":"integer","minimum":0,"maximum":23},"timezone":{"type":"string","maxLength":80},"locale":{"type":"string","enum":["en","de"]},"cooldownHours":{"type":"integer","minimum":1,"maximum":720},"lowStockThresholdPercent":{"type":"integer","minimum":1,"maximum":500},"expiryWindowDays":{"type":"integer","minimum":0,"maximum":3650},"expiryFieldKey":{"type":"string","maxLength":64,"pattern":"^[a-z][a-z0-9_]{0,63}$"},"maintenanceWindowDays":{"type":"integer","minimum":0,"maximum":3650},"maintenanceFieldKey":{"type":"string","maxLength":64,"pattern":"^[a-z][a-z0-9_]{0,63}$"},"returnDueWindowDays":{"type":"integer","minimum":0,"maximum":365},"emailEnabled":{"type":"boolean","default":false},"pushEnabled":{"type":"boolean","default":false},"slackEnabled":{"type":"boolean","default":false},"teamsEnabled":{"type":"boolean","default":false},"webhookEnabled":{"type":"boolean","default":false}}},"WebhookEventType":{"type":"string","description":"Stable integration event name selected when configuring an endpoint.","enum":["inventory.resource.created","inventory.resource.updated","inventory.resource.deleted","inventory.resource.merged","inventory.stock.movement.created"]},"WebhookOutboundEventType":{"type":"string","description":"Event name sent in a delivery. Test actions use a dedicated type that cannot be subscribed to.","enum":["inventory.resource.created","inventory.resource.updated","inventory.resource.deleted","inventory.resource.merged","inventory.stock.movement.created","inventory.webhook.test"]},"WebhookEndpointCreate":{"type":"object","additionalProperties":false,"required":["name","url","eventTypes"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"url":{"type":"string","format":"uri","minLength":1,"maxLength":2048,"description":"Absolute HTTPS delivery target. Private and local networks are blocked unless the deployment explicitly opts in."},"eventTypes":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"$ref":"#/components/schemas/WebhookEventType"}},"enabled":{"type":"boolean","default":true}}},"WebhookEndpointPatch":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"url":{"type":"string","format":"uri","minLength":1,"maxLength":2048,"description":"Complete replacement HTTPS target; the current stored target cannot be recovered from its redacted response form."},"eventTypes":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"$ref":"#/components/schemas/WebhookEventType"}},"enabled":{"type":"boolean"}}},"WebhookEndpoint":{"type":"object","additionalProperties":false,"required":["id","name","target","eventTypes","enabled","failureCount","lastSuccessAt","lastFailureAt","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"target":{"type":"string","description":"Redacted delivery target. Query values and secret path segments are never returned.","examples":["https://hooks.example.com/…"]},"eventTypes":{"type":"array","uniqueItems":true,"items":{"$ref":"#/components/schemas/WebhookEventType"}},"enabled":{"type":"boolean"},"failureCount":{"type":"integer","minimum":0},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"lastFailureAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookListResponse":{"type":"object","additionalProperties":false,"required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"WebhookResponse":{"type":"object","additionalProperties":false,"required":["webhook"],"properties":{"webhook":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"WebhookCreatedResponse":{"type":"object","additionalProperties":false,"required":["webhook","secret"],"properties":{"webhook":{"$ref":"#/components/schemas/WebhookEndpoint"},"secret":{"type":"string","description":"Signing secret disclosed once. It is encrypted at rest and cannot be retrieved later."}}},"WebhookSecretResponse":{"type":"object","additionalProperties":false,"required":["secret"],"properties":{"secret":{"type":"string","description":"Replacement signing secret disclosed once."}}},"WebhookTestResponse":{"type":"object","additionalProperties":false,"required":["eventId","deliveryId"],"properties":{"eventId":{"type":"string","format":"uuid"},"deliveryId":{"type":"string","format":"uuid"}}},"WebhookDeliveryStatus":{"type":"string","enum":["pending","processing","succeeded","failed"]},"WebhookDeliveryEvent":{"type":"object","additionalProperties":false,"required":["id","type","occurredAt"],"properties":{"id":{"type":"string","format":"uuid"},"type":{"$ref":"#/components/schemas/WebhookOutboundEventType"},"occurredAt":{"type":"string","format":"date-time"}}},"WebhookDelivery":{"type":"object","additionalProperties":false,"required":["id","status","attempts","nextAttemptAt","httpStatus","error","deliveredAt","createdAt","event"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/WebhookDeliveryStatus"},"attempts":{"type":"integer","minimum":0},"nextAttemptAt":{"type":"string","format":"date-time"},"httpStatus":{"type":["integer","null"],"minimum":100,"maximum":599},"error":{"type":["string","null"]},"deliveredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"event":{"$ref":"#/components/schemas/WebhookDeliveryEvent"}}},"WebhookDeliveryState":{"type":"object","additionalProperties":false,"description":"Delivery state returned immediately after a manual retry; fetch the delivery list for its event summary.","required":["id","status","attempts","nextAttemptAt","httpStatus","error","deliveredAt","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/WebhookDeliveryStatus"},"attempts":{"type":"integer","minimum":0},"nextAttemptAt":{"type":"string","format":"date-time"},"httpStatus":{"type":["integer","null"],"minimum":100,"maximum":599},"error":{"type":["string","null"]},"deliveredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}},"WebhookDeliveryListResponse":{"type":"object","additionalProperties":false,"required":["deliveries"],"properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"WebhookDeliveryResponse":{"type":"object","additionalProperties":false,"required":["delivery"],"properties":{"delivery":{"$ref":"#/components/schemas/WebhookDeliveryState"}}},"WebhookRunResponse":{"type":"object","additionalProperties":false,"required":["processed","results"],"properties":{"processed":{"type":"integer","minimum":0},"results":{"type":"array","items":{"type":"string","enum":["succeeded","failed"]}}}},"WebhookEvent":{"type":"object","additionalProperties":false,"required":["id","type","apiVersion","occurredAt","actor","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Stable event identifier used by receivers for deduplication across retries."},"type":{"$ref":"#/components/schemas/WebhookOutboundEventType"},"apiVersion":{"type":"string","const":"1"},"occurredAt":{"type":"string","format":"date-time"},"actor":{"type":["string","null"],"description":"Identity responsible for the event when one is available."},"data":{"type":"object","additionalProperties":true,"description":"Event-specific snapshot: create, update, and delete events include `resource`; updates also include `changedFields`; merges include `keptResource`, `removedResource`, `keptResourceId`, and `removedResourceId`; stock movement events include the immutable `movement` snapshot; test deliveries include `test: true` and a human-readable `message`."}}},"AccessRoleKey":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_-]{0,63}$","description":"Stable lowercase identifier for a built-in or custom role.","examples":["editor","warehouse_team"]},"AppPermission":{"type":"string","description":"Granular workspace-wide capability assigned to a role.","enum":["inventory.read","inventory.create","inventory.update","inventory.delete","inventory.import","inventory.export","stock.read","stock.manage","assignments.read","assignments.manage","counts.read","counts.manage","spatial.read","spatial.manage","orders.read","orders.manage","workflows.read","workflows.manage","labels.read","labels.manage","ai.use","settings.inventory-types.manage","settings.custom-fields.manage","settings.languages.manage","users.manage","roles.manage","sharing.manage","tokens.manage","tokens.delegate","webhooks.manage"]},"InventoryRulePermission":{"type":"string","description":"Permission that a conditional rule may grant for matching inventory items.","enum":["inventory.update","inventory.delete","stock.manage","assignments.manage","counts.manage","spatial.manage","ai.use"]},"PermissionDefinition":{"type":"object","additionalProperties":false,"required":["key","label","description"],"properties":{"key":{"$ref":"#/components/schemas/AppPermission"},"label":{"type":"string"},"description":{"type":"string"}}},"PermissionGroup":{"type":"object","additionalProperties":false,"required":["key","label","description","permissions"],"properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionDefinition"}}}},"AccessRoleInput":{"type":"object","additionalProperties":false,"required":["key","name"],"properties":{"key":{"$ref":"#/components/schemas/AccessRoleKey"},"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000,"default":""},"permissions":{"type":"array","maxItems":30,"default":[],"items":{"$ref":"#/components/schemas/AppPermission"}}}},"AccessRolePatch":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000},"permissions":{"type":"array","maxItems":30,"items":{"$ref":"#/components/schemas/AppPermission"}}}},"AccessRole":{"type":"object","additionalProperties":false,"required":["key","name","description","permissions","isSystem"],"properties":{"key":{"$ref":"#/components/schemas/AccessRoleKey"},"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000},"permissions":{"type":"array","maxItems":30,"items":{"$ref":"#/components/schemas/AppPermission"}},"isSystem":{"type":"boolean","description":"Whether the role is built in and cannot be deleted."},"memberCount":{"type":"integer","minimum":0,"description":"Number of active users assigned to the role; included in role-list and create responses."},"createdBy":{"type":["string","null"],"maxLength":320},"updatedBy":{"type":["string","null"],"maxLength":320},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"AccessRuleCondition":{"type":"object","additionalProperties":false,"required":["field","operator"],"description":"One condition in a rule. Every condition in the same rule must match; comparisons are case-insensitive for strings.","properties":{"field":{"type":"string","pattern":"^(id|name|type|status|sku|location|serialNumber|priority|tags|categories|createdBy|customFields\\.[A-Za-z0-9_-]{1,120})$","description":"Built-in inventory field or a custom field addressed as customFields.KEY.","examples":["status","categories","customFields.department"]},"operator":{"type":"string","enum":["equals","not_equals","contains","starts_with","exists","not_exists"]},"value":{"description":"Comparison value. Required except for exists and not_exists, where it is ignored.","oneOf":[{"type":"string","maxLength":500},{"type":"number"},{"type":"boolean"},{"type":"null"}]}}},"InventoryAccessRuleInput":{"type":"object","additionalProperties":false,"required":["name","roleKey","permissions","conditions"],"description":"Additive item-specific access grant. Multiple enabled rules are ORed; all conditions inside this rule are ANDed.","properties":{"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","maxLength":1000,"default":""},"roleKey":{"$ref":"#/components/schemas/AccessRoleKey"},"permissions":{"type":"array","minItems":1,"maxItems":7,"items":{"$ref":"#/components/schemas/InventoryRulePermission"}},"conditions":{"type":"array","minItems":1,"maxItems":12,"description":"Conditions combined with logical AND.","items":{"$ref":"#/components/schemas/AccessRuleCondition"}},"enabled":{"type":"boolean","default":true},"priority":{"type":"integer","minimum":0,"maximum":10000,"default":100,"description":"Display and evaluation order; lower values come first and do not override other matching rules."}},"examples":[{"name":"Update XYZ items","description":"Let members of the ABC role update items whose name contains xyz.","roleKey":"abc","permissions":["inventory.update"],"conditions":[{"field":"name","operator":"contains","value":"xyz"}],"enabled":true,"priority":100}]},"InventoryAccessRulePatch":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","maxLength":1000},"roleKey":{"$ref":"#/components/schemas/AccessRoleKey"},"permissions":{"type":"array","minItems":1,"maxItems":7,"items":{"$ref":"#/components/schemas/InventoryRulePermission"}},"conditions":{"type":"array","minItems":1,"maxItems":12,"description":"Conditions combined with logical AND.","items":{"$ref":"#/components/schemas/AccessRuleCondition"}},"enabled":{"type":"boolean"},"priority":{"type":"integer","minimum":0,"maximum":10000}}},"InventoryAccessRule":{"type":"object","additionalProperties":false,"required":["id","name","description","roleKey","permissions","conditions","enabled","priority","createdAt","updatedAt"],"description":"Additive permission grant for matching inventory items. Rules never deny permissions already granted by a role; any matching enabled rule may grant access.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","maxLength":1000},"roleKey":{"$ref":"#/components/schemas/AccessRoleKey"},"permissions":{"type":"array","minItems":1,"maxItems":7,"items":{"$ref":"#/components/schemas/InventoryRulePermission"}},"conditions":{"type":"array","minItems":1,"maxItems":12,"description":"Conditions combined with logical AND.","items":{"$ref":"#/components/schemas/AccessRuleCondition"}},"enabled":{"type":"boolean"},"priority":{"type":"integer","minimum":0,"maximum":10000},"createdBy":{"type":["string","null"],"maxLength":320},"updatedBy":{"type":["string","null"],"maxLength":320},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SpatialVector3":{"type":"array","minItems":3,"maxItems":3,"items":{"type":"number","minimum":-10000,"maximum":10000},"description":"XYZ values in metres."},"SpatialDimensions":{"type":"array","minItems":3,"maxItems":3,"items":{"type":"number","minimum":0,"maximum":100}},"SpatialQuaternion":{"type":"array","minItems":4,"maxItems":4,"items":{"type":"number","minimum":-1,"maximum":1},"description":"Normalized XYZW quaternion."},"SpatialMatrix4":{"type":"array","minItems":16,"maxItems":16,"items":{"type":"number","minimum":-10000,"maximum":10000},"description":"Column-major affine 4x4 matrix."},"SpatialReferencePoint":{"type":"object","additionalProperties":false,"required":["id","localPosition","latitude","longitude"],"properties":{"id":{"type":"string","minLength":1,"maxLength":80},"label":{"type":"string","minLength":1,"maxLength":120},"localPosition":{"$ref":"#/components/schemas/SpatialVector3"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number","minimum":-12000,"maximum":100000}}},"SpatialGeoreference":{"type":"object","additionalProperties":false,"required":["latitude","longitude","headingDegrees","capturedAt","source"],"description":"Geographic anchor for one ARKit coordinate space. headingDegrees is the bearing of AR local -Z measured clockwise from true north; latitude/longitude/altitude identify localReferencePosition.","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number","minimum":-12000,"maximum":100000},"headingDegrees":{"type":"number","minimum":0,"exclusiveMaximum":360},"horizontalAccuracy":{"type":"number","minimum":0,"maximum":100000},"verticalAccuracy":{"type":"number","minimum":0,"maximum":100000},"capturedAt":{"type":"string","format":"date-time"},"source":{"type":"string","enum":["gps","manual","qr-marker","app-clip","other"]},"localReferencePosition":{"allOf":[{"$ref":"#/components/schemas/SpatialVector3"}],"default":[0,0,0]},"referencePoints":{"type":"array","maxItems":64,"items":{"$ref":"#/components/schemas/SpatialReferencePoint"}},"entryMarkerCode":{"type":"string","minLength":1,"maxLength":240}}},"SpatialStructureCreate":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":240},"description":{"type":"string","maxLength":10000,"default":""},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]}}},"SpatialStructurePatch":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":240},"description":{"type":"string","maxLength":10000},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]}}},"SpatialStructureSummary":{"type":"object","required":["id","name","description","floorCount","roomCount","activeScanCount","coordinateSpaceCount","bounds","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}],"description":"Canonical building map marker, not necessarily the anchor for every room scan."},"floorCount":{"type":"integer","minimum":0},"roomCount":{"type":"integer","minimum":0},"activeScanCount":{"type":"integer","minimum":0},"coordinateSpaceCount":{"type":"integer","minimum":0},"bounds":{"oneOf":[{"type":"object","required":["min","max"],"properties":{"min":{"$ref":"#/components/schemas/SpatialVector3"},"max":{"$ref":"#/components/schemas/SpatialVector3"}}},{"type":"null"}],"description":"Local bounds only when every active scan shares one explicit coordinateSpaceId; otherwise null."},"boundsCoordinateSpaceId":{"type":["string","null"],"format":"uuid"},"boundsGeoreference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"RoomSceneElement":{"type":"object","additionalProperties":false,"required":["id","category","dimensions","transform","confidence"],"properties":{"id":{"type":"string","format":"uuid"},"category":{"type":"string","minLength":1,"maxLength":80},"dimensions":{"$ref":"#/components/schemas/SpatialDimensions"},"transform":{"$ref":"#/components/schemas/SpatialMatrix4"},"polygonCorners":{"type":"array","minItems":3,"maxItems":1024,"description":"Ordered RoomPlan boundary in the surface-local coordinate system; preferred over dimensions for non-rectangular floors.","items":{"$ref":"#/components/schemas/SpatialVector3"}},"confidence":{"type":"string","enum":["low","medium","high"]}}},"RoomScene":{"type":"object","additionalProperties":false,"required":["schemaVersion","coordinateSystem","units","matrixOrder","worldFromModel","webFromWorld","bounds","surfaces","objects"],"properties":{"schemaVersion":{"type":"integer","const":1},"coordinateSystem":{"type":"string","const":"arkit-right-handed-y-up"},"units":{"type":"string","const":"meter"},"matrixOrder":{"type":"string","const":"column-major"},"worldFromModel":{"$ref":"#/components/schemas/SpatialMatrix4"},"webFromWorld":{"allOf":[{"$ref":"#/components/schemas/SpatialMatrix4"}],"description":"Visualization transform shared by every scan with the same coordinateSpaceId."},"bounds":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"$ref":"#/components/schemas/SpatialVector3"},"max":{"$ref":"#/components/schemas/SpatialVector3"}}},"surfaces":{"type":"array","maxItems":4096,"items":{"$ref":"#/components/schemas/RoomSceneElement"}},"objects":{"type":"array","maxItems":2048,"items":{"$ref":"#/components/schemas/RoomSceneElement"}}}},"RoomScanAsset":{"type":"object","required":["id","kind","name","mimeType","size","checksumSha256","url","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["world_map","model_usdz","structure_model","guide_image","textured_mesh","gaussian_splat"]},"name":{"type":"string"},"mimeType":{"type":"string"},"size":{"type":"integer","minimum":0},"checksumSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"url":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"RoomScanSummary":{"type":"object","required":["id","roomResourceId","roomName","revision","status","capturedAt","createdAt","updatedAt","placementCount","assets","keyframeCount"],"properties":{"id":{"type":"string","format":"uuid"},"roomResourceId":{"type":"string","format":"uuid"},"roomName":{"type":"string"},"structureId":{"type":["string","null"],"format":"uuid"},"structureName":{"type":["string","null"]},"coordinateSpaceId":{"type":["string","null"],"format":"uuid"},"floorIdentifier":{"type":["string","null"]},"floorIndex":{"type":["integer","null"]},"roomIdentifier":{"type":["string","null"]},"layoutTransform":{"oneOf":[{"$ref":"#/components/schemas/SpatialMatrix4"},{"type":"null"}],"description":"Optional saved world-from-model transform used to arrange the room with the other rooms on its floor."},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]},"revision":{"type":"integer","minimum":1},"status":{"type":"string","enum":["active","superseded"]},"capturedAt":{"type":"string","format":"date-time"},"deviceModel":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"placementCount":{"type":"integer","minimum":0},"keyframeCount":{"type":"integer","minimum":0,"maximum":32,"description":"Number of calibrated reference photos. Full metadata is returned only by the room-scene detail endpoint."},"assets":{"type":"array","items":{"$ref":"#/components/schemas/RoomScanAsset"}}}},"RoomScanUploadResult":{"type":"object","additionalProperties":false,"required":["id","replayed"],"properties":{"id":{"type":"string","format":"uuid"},"replayed":{"type":"boolean"}}},"RoomLayoutTransformPatch":{"type":"object","additionalProperties":false,"required":["transform"],"properties":{"transform":{"oneOf":[{"$ref":"#/components/schemas/SpatialMatrix4"},{"type":"null"}]}}},"SpatialPlacementInput":{"type":"object","additionalProperties":false,"required":["position","orientation","confidence","method","capturedAt"],"properties":{"position":{"$ref":"#/components/schemas/SpatialVector3"},"orientation":{"$ref":"#/components/schemas/SpatialQuaternion"},"extent":{"$ref":"#/components/schemas/SpatialDimensions"},"confidence":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["scene-depth","mesh-raycast","plane-raycast","manual"]},"anchorIdentifier":{"type":"string","format":"uuid"},"capturedAt":{"type":"string","format":"date-time"},"localizationEvidence":{"$ref":"#/components/schemas/PhotoLocalizationEvidence"}}},"PhotoLocalizationEvidence":{"type":"object","additionalProperties":false,"required":["matchedKeyframeId","distance","confidence"],"properties":{"matchedKeyframeId":{"type":"string","format":"uuid"},"distance":{"type":"number","minimum":0,"maximum":1000000},"confidence":{"type":"number","minimum":0,"maximum":1},"cameraPositionError":{"type":"number","minimum":0,"maximum":100}}},"RoomCameraKeyframeInput":{"type":"object","additionalProperties":false,"required":["id","fileField","capturedAt","timestamp","cameraTransform","intrinsics","width","height","orientation","quality"],"properties":{"id":{"type":"string","format":"uuid"},"fileField":{"type":"string","description":"Must exactly equal keyframe:<id> and name one JPEG multipart part."},"capturedAt":{"type":"string","format":"date-time"},"timestamp":{"type":"number","minimum":0,"description":"ARFrame session timestamp in seconds."},"cameraTransform":{"allOf":[{"$ref":"#/components/schemas/SpatialMatrix4"}],"description":"Column-major worldFromCamera transform in the scan coordinate space."},"intrinsics":{"type":"array","minItems":9,"maxItems":9,"items":{"type":"number"},"description":"Column-major ARKit 3x3 pinhole-camera matrix for the encoded native-raster pixel dimensions. Apply orientation only when displaying the JPEG."},"width":{"type":"integer","minimum":1,"maximum":4096},"height":{"type":"integer","minimum":1,"maximum":4096},"orientation":{"type":"string","enum":["up","up-mirrored","down","down-mirrored","left-mirrored","right","right-mirrored","left"]},"quality":{"type":"number","minimum":0,"maximum":1},"featureDescriptor":{"type":["object","null"],"properties":{"format":{"type":"string","const":"vision-feature-print-v1"},"dataBase64":{"type":"string","maxLength":65536}}}}},"RoomCameraKeyframe":{"allOf":[{"type":"object","additionalProperties":false,"required":["id","capturedAt","timestamp","cameraTransform","intrinsics","width","height","orientation","quality","mimeType","size","checksumSha256","url"],"properties":{"id":{"type":"string","format":"uuid"},"capturedAt":{"type":"string","format":"date-time"},"timestamp":{"type":"number","minimum":0},"cameraTransform":{"$ref":"#/components/schemas/SpatialMatrix4"},"intrinsics":{"type":"array","minItems":9,"maxItems":9,"items":{"type":"number"}},"width":{"type":"integer","minimum":1,"maximum":4096},"height":{"type":"integer","minimum":1,"maximum":4096},"orientation":{"type":"string","enum":["up","up-mirrored","down","down-mirrored","left-mirrored","right","right-mirrored","left"]},"quality":{"type":"number","minimum":0,"maximum":1},"mimeType":{"type":"string","const":"image/jpeg"},"size":{"type":"integer","minimum":1,"maximum":6291456},"checksumSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"url":{"type":"string"}}}]},"RoomSceneManifest":{"type":"object","required":["room","scan","placements"],"properties":{"structureId":{"type":["string","null"],"format":"uuid"},"structureName":{"type":["string","null"]},"coordinateSpaceId":{"type":["string","null"],"format":"uuid"},"floorIdentifier":{"type":["string","null"]},"floorIndex":{"type":["integer","null"]},"roomIdentifier":{"type":["string","null"]},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]},"room":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"}}},"scan":{"type":"object","required":["id","revision","status","scene","capturedAt","assets","keyframes"],"properties":{"id":{"type":"string","format":"uuid"},"structureId":{"type":["string","null"],"format":"uuid"},"structureName":{"type":["string","null"]},"coordinateSpaceId":{"type":["string","null"],"format":"uuid"},"floorIdentifier":{"type":["string","null"]},"floorIndex":{"type":["integer","null"]},"roomIdentifier":{"type":["string","null"]},"layoutTransform":{"oneOf":[{"$ref":"#/components/schemas/SpatialMatrix4"},{"type":"null"}],"description":"Optional saved world-from-model transform used to arrange the room with the other rooms on its floor."},"georeference":{"oneOf":[{"$ref":"#/components/schemas/SpatialGeoreference"},{"type":"null"}]},"revision":{"type":"integer","minimum":1},"status":{"type":"string","enum":["active","superseded"]},"scene":{"$ref":"#/components/schemas/RoomScene"},"capturedAt":{"type":"string","format":"date-time"},"deviceModel":{"type":["string","null"]},"assets":{"type":"array","items":{"$ref":"#/components/schemas/RoomScanAsset"}},"keyframes":{"type":"array","maxItems":32,"items":{"$ref":"#/components/schemas/RoomCameraKeyframe"}}}},"placements":{"type":"array","items":{"type":"object","required":["id","resource","position","orientation","confidence","method","capturedAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"resource":{"type":"object","required":["id","name","type","status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"location":{"type":["string","null"]},"cover":{"type":["object","null"]}}},"position":{"$ref":"#/components/schemas/SpatialVector3"},"orientation":{"$ref":"#/components/schemas/SpatialQuaternion"},"extent":{"oneOf":[{"$ref":"#/components/schemas/SpatialDimensions"},{"type":"null"}]},"confidence":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["scene-depth","mesh-raycast","plane-raycast","manual"]},"anchorIdentifier":{"type":["string","null"],"format":"uuid"},"localizationEvidence":{"oneOf":[{"$ref":"#/components/schemas/PhotoLocalizationEvidence"},{"type":"null"}]},"capturedAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"DefinitionKey":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_-]{0,63}$"},"InventoryTypeKey":{"allOf":[{"$ref":"#/components/schemas/DefinitionKey"}],"description":"Stable key of an administrator-configurable inventory type."},"RelationTypeKey":{"allOf":[{"$ref":"#/components/schemas/DefinitionKey"}],"description":"Stable key of an administrator-configurable directed relationship type."},"InventoryTypeInput":{"type":"object","required":["key","label"],"additionalProperties":false,"properties":{"key":{"$ref":"#/components/schemas/InventoryTypeKey"},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000,"default":""},"color":{"type":"string","minLength":1,"maxLength":32,"default":"#635bff"},"icon":{"type":"string","minLength":1,"maxLength":80,"default":"box"},"canContain":{"type":"boolean","default":false,"description":"Records of this type can be used as parents and structured stock locations."},"spatialContainment":{"type":"boolean","default":false,"description":"Automatically derive containment from map polygons. Requires canContain."},"position":{"type":"integer","minimum":0,"maximum":100000,"default":0}}},"InventoryTypePatch":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000},"color":{"type":"string","minLength":1,"maxLength":32},"icon":{"type":"string","minLength":1,"maxLength":80},"canContain":{"type":"boolean"},"spatialContainment":{"type":"boolean"},"position":{"type":"integer","minimum":0,"maximum":100000},"archived":{"type":"boolean","description":"Archive when true or restore when false."}}},"InventoryTypeDefinition":{"type":"object","required":["key","label","description","color","icon","canContain","spatialContainment","position","isSystem","createdBy","updatedBy","createdAt","updatedAt","archivedAt"],"properties":{"key":{"$ref":"#/components/schemas/InventoryTypeKey"},"label":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"canContain":{"type":"boolean"},"spatialContainment":{"type":"boolean"},"position":{"type":"integer","minimum":0},"isSystem":{"type":"boolean"},"createdBy":{"type":["string","null"]},"updatedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"RelationTypeInput":{"type":"object","required":["key","label","inverseLabel"],"additionalProperties":false,"properties":{"key":{"$ref":"#/components/schemas/RelationTypeKey"},"label":{"type":"string","minLength":1,"maxLength":120},"inverseLabel":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000,"default":""},"allowManual":{"type":"boolean","default":true},"position":{"type":"integer","minimum":0,"maximum":100000,"default":0}}},"RelationTypePatch":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"label":{"type":"string","minLength":1,"maxLength":120},"inverseLabel":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000},"allowManual":{"type":"boolean"},"position":{"type":"integer","minimum":0,"maximum":100000},"archived":{"type":"boolean","description":"Archive when true or restore when false."}}},"RelationTypeDefinition":{"type":"object","required":["key","label","inverseLabel","description","allowManual","spatial","position","isSystem","createdBy","updatedBy","createdAt","updatedAt","archivedAt"],"properties":{"key":{"$ref":"#/components/schemas/RelationTypeKey"},"label":{"type":"string"},"inverseLabel":{"type":"string"},"description":{"type":"string"},"allowManual":{"type":"boolean"},"spatial":{"type":"boolean","description":"Whether this built-in definition may be generated from geometry."},"position":{"type":"integer","minimum":0},"isSystem":{"type":"boolean"},"createdBy":{"type":["string","null"]},"updatedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"ResourceReference":{"type":"object","required":["id","name","type","status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"status":{"type":"string","enum":["available","in-use","maintenance","archived"]}}},"ResourceRelationInput":{"type":"object","required":["sourceResourceId","targetResourceId","relationTypeKey"],"additionalProperties":false,"properties":{"sourceResourceId":{"type":"string","format":"uuid","description":"Directed parent or subject endpoint."},"targetResourceId":{"type":"string","format":"uuid","description":"Directed child or object endpoint."},"relationTypeKey":{"$ref":"#/components/schemas/RelationTypeKey"}}},"ResourceRelationRecord":{"type":"object","required":["id","sourceResourceId","targetResourceId","relationTypeKey","origin","sourceFeatureId","targetFeatureId","createdBy","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"sourceResourceId":{"type":"string","format":"uuid"},"targetResourceId":{"type":"string","format":"uuid"},"relationTypeKey":{"$ref":"#/components/schemas/RelationTypeKey"},"origin":{"type":"string","enum":["manual","spatial"]},"sourceFeatureId":{"type":["string","null"]},"targetFeatureId":{"type":["string","null"]},"createdBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"ResourceRelation":{"allOf":[{"$ref":"#/components/schemas/ResourceRelationRecord"},{"type":"object","required":["source","target","relationType"],"properties":{"source":{"oneOf":[{"$ref":"#/components/schemas/ResourceReference"},{"type":"null"}]},"target":{"oneOf":[{"$ref":"#/components/schemas/ResourceReference"},{"type":"null"}]},"relationType":{"oneOf":[{"$ref":"#/components/schemas/RelationTypeDefinition"},{"type":"null"}]}}}]},"CustomFieldOption":{"type":"object","required":["value","label"],"additionalProperties":false,"properties":{"value":{"type":"string","minLength":1,"maxLength":120,"description":"Stable value stored in customFields."},"label":{"type":"string","minLength":1,"maxLength":120},"color":{"type":"string","minLength":1,"maxLength":32}}},"CustomFieldReferenceOption":{"type":"object","required":["id","entityType","label","description","status"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"entityType":{"type":"string","enum":["inventory","stock_unit"]},"label":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"}}},"CustomFieldValues":{"type":"object","maxProperties":100,"description":"Values keyed by stable custom-field definition keys. Types and required values are checked against active definitions applicable to the resource.","additionalProperties":{"oneOf":[{"type":"string","maxLength":20000},{"type":"number"},{"type":"boolean"},{"type":"array","maxItems":100,"items":{"type":"string","maxLength":120}}]}},"CustomFieldDefinitionInput":{"type":"object","required":["entityType","label","fieldType"],"additionalProperties":false,"properties":{"entityType":{"type":"string","enum":["inventory","stock_unit"],"description":"Whether values live on inventory resources or serialized stock units."},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","description":"Stable API/storage identifier. Generated from label when omitted and immutable after creation."},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000,"default":""},"placeholder":{"type":"string","maxLength":240,"default":""},"fieldType":{"type":"string","enum":["text","textarea","number","boolean","date","datetime","select","multi_select","reference","email","url"]},"required":{"type":"boolean","default":false},"minValue":{"type":["number","null"],"default":null,"description":"Inclusive minimum for number fields; null for other field types."},"maxValue":{"type":["number","null"],"default":null,"description":"Inclusive maximum for number fields; null for other field types."},"step":{"type":["number","null"],"exclusiveMinimum":0,"default":null,"description":"Positive increment for number fields; null for other field types."},"resourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"description":"Applicable inventory types. An empty array matches every type.","items":{"$ref":"#/components/schemas/InventoryTypeKey"},"default":[]},"categories":{"type":"array","maxItems":40,"uniqueItems":true,"description":"Applicable category names, matched case-insensitively. An empty array matches every category; when resourceTypes is also set, both targets must match.","items":{"type":"string","minLength":1,"maxLength":120},"default":[]},"options":{"type":"array","maxItems":100,"description":"Required and non-empty for select and multi_select fields; empty for every other field type.","items":{"$ref":"#/components/schemas/CustomFieldOption"},"default":[]},"referenceEntityType":{"type":["string","null"],"enum":["inventory","stock_unit",null],"default":null,"description":"Required for reference fields and null for all other field types."},"referenceMultiple":{"type":"boolean","default":false,"description":"Whether a reference field stores an array of target UUIDs instead of one UUID."},"referenceResourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"$ref":"#/components/schemas/InventoryTypeKey"},"default":[],"description":"Allowed target or parent inventory types; empty matches every type."},"referenceCategories":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120},"default":[],"description":"Allowed target or parent inventory categories; empty matches every category."},"referenceStatuses":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":32},"default":[],"description":"Allowed target statuses; empty matches every status."},"position":{"type":"integer","minimum":0,"maximum":100000,"default":0}}},"CustomFieldDefinitionPatch":{"type":"object","required":["revision"],"minProperties":2,"additionalProperties":false,"description":"The last observed revision plus a non-empty subset of mutable definition fields. Entity type and key cannot be changed.","properties":{"revision":{"type":"integer","minimum":1},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000},"placeholder":{"type":"string","maxLength":240},"fieldType":{"type":"string","enum":["text","textarea","number","boolean","date","datetime","select","multi_select","reference","email","url"]},"required":{"type":"boolean"},"minValue":{"type":["number","null"]},"maxValue":{"type":["number","null"]},"step":{"type":["number","null"],"exclusiveMinimum":0},"resourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"$ref":"#/components/schemas/InventoryTypeKey"}},"categories":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120}},"options":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CustomFieldOption"}},"referenceEntityType":{"type":["string","null"],"enum":["inventory","stock_unit",null]},"referenceMultiple":{"type":"boolean"},"referenceResourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"$ref":"#/components/schemas/InventoryTypeKey"}},"referenceCategories":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120}},"referenceStatuses":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":32}},"position":{"type":"integer","minimum":0,"maximum":100000}}},"CustomFieldDefinition":{"type":"object","required":["id","entityType","key","label","description","placeholder","fieldType","required","minValue","maxValue","step","resourceTypes","categories","options","referenceEntityType","referenceMultiple","referenceResourceTypes","referenceCategories","referenceStatuses","position","revision","createdBy","updatedBy","createdAt","updatedAt","archivedAt"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"entityType":{"type":"string","enum":["inventory","stock_unit"]},"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":5000},"placeholder":{"type":"string","maxLength":240},"fieldType":{"type":"string","enum":["text","textarea","number","boolean","date","datetime","select","multi_select","reference","email","url"]},"required":{"type":"boolean"},"minValue":{"type":["number","null"]},"maxValue":{"type":["number","null"]},"step":{"type":["number","null"],"exclusiveMinimum":0},"resourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"$ref":"#/components/schemas/InventoryTypeKey"}},"categories":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120}},"options":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CustomFieldOption"}},"referenceEntityType":{"type":["string","null"],"enum":["inventory","stock_unit",null]},"referenceMultiple":{"type":"boolean"},"referenceResourceTypes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"$ref":"#/components/schemas/InventoryTypeKey"}},"referenceCategories":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120}},"referenceStatuses":{"type":"array","maxItems":40,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":32}},"position":{"type":"integer","minimum":0,"maximum":100000},"revision":{"type":"integer","minimum":1,"description":"Incremented by every update and soft deletion."},"createdBy":{"type":["string","null"],"maxLength":320},"updatedBy":{"type":["string","null"],"maxLength":320},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"LabelElement":{"oneOf":[{"type":"object","title":"QR or barcode element","required":["type","x","y","width","height","visible"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["qr","barcode"]},"x":{"type":"number","minimum":0,"maximum":100},"y":{"type":"number","minimum":0,"maximum":100},"width":{"type":"number","exclusiveMinimum":0,"maximum":100},"height":{"type":"number","exclusiveMinimum":0,"maximum":100},"visible":{"type":"boolean"}}},{"type":"object","title":"Object image element","required":["type","x","y","width","height","visible"],"additionalProperties":false,"properties":{"type":{"type":"string","const":"image"},"x":{"type":"number","minimum":0,"maximum":100},"y":{"type":"number","minimum":0,"maximum":100},"width":{"type":"number","exclusiveMinimum":0,"maximum":100},"height":{"type":"number","exclusiveMinimum":0,"maximum":100},"visible":{"type":"boolean"},"fit":{"type":"string","enum":["cover","contain"],"default":"cover"}}},{"type":"object","title":"Text element","required":["type","x","y","width","height","visible"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["name","identifier","url","location"]},"x":{"type":"number","minimum":0,"maximum":100},"y":{"type":"number","minimum":0,"maximum":100},"width":{"type":"number","exclusiveMinimum":0,"maximum":100},"height":{"type":"number","exclusiveMinimum":0,"maximum":100},"visible":{"type":"boolean"},"fontSizeMm":{"type":"number","exclusiveMinimum":0,"maximum":100},"align":{"type":"string","enum":["left","center","right"],"default":"left"}}}],"description":"A normalized percentage box. The element must fit entirely inside the label; options are restricted by element type."},"LabelElements":{"type":"array","maxItems":7,"description":"At most one element of each type. A visible object image may not overlap a visible QR code. The image element prints the resource cover image; QR and URL elements use the compact resource link.","items":{"$ref":"#/components/schemas/LabelElement"}},"LabelSetupInput":{"type":"object","required":["name","widthMm","heightMm","elements"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":160},"widthMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"heightMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"elements":{"$ref":"#/components/schemas/LabelElements"}}},"LabelSetupPatch":{"type":"object","required":["revision"],"minProperties":2,"additionalProperties":false,"description":"The last observed revision plus at least one changed setup property.","properties":{"revision":{"type":"integer","minimum":1},"name":{"type":"string","minLength":1,"maxLength":160},"widthMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"heightMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"elements":{"$ref":"#/components/schemas/LabelElements"}}},"LabelSetup":{"type":"object","required":["id","name","widthMm","heightMm","elements","revision","createdAt","updatedAt"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":160},"widthMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"heightMm":{"type":"number","exclusiveMinimum":0,"maximum":1000},"elements":{"$ref":"#/components/schemas/LabelElements"},"revision":{"type":"integer","minimum":1,"description":"Incremented by every successful update."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"InventoryCount":{"type":"object","required":["count","confidence","detectedItem","isExact","explanation","warnings","markers","model"],"properties":{"count":{"type":"integer","minimum":0,"maximum":1000000},"confidence":{"type":"number","minimum":0,"maximum":1},"detectedItem":{"type":"string","minLength":1,"maxLength":240},"isExact":{"type":"boolean","description":"True only when every counted instance is individually visible without meaningful ambiguity. The current zero-shot SAM 3 provider returns false so clients require review."},"explanation":{"type":"string","minLength":1,"maxLength":1000},"warnings":{"type":"array","maxItems":10,"items":{"type":"string","minLength":1,"maxLength":240}},"markers":{"type":"array","description":"One bounding-box center per counted item on a 0...1000 image grid, measured from the top-left corner of the orientation-corrected full image.","items":{"type":"object","additionalProperties":false,"required":["x","y"],"properties":{"x":{"type":"integer","minimum":0,"maximum":1000},"y":{"type":"integer","minimum":0,"maximum":1000}}}},"model":{"type":"string"}}},"InventoryRecognitionObservation":{"type":"object","additionalProperties":false,"required":["label","category","brand","model","color","material","visibleText","searchTerms","confidence"],"properties":{"label":{"type":"string","minLength":1,"maxLength":160},"category":{"type":"string","minLength":1,"maxLength":160},"brand":{"type":["string","null"],"minLength":1,"maxLength":160},"model":{"type":["string","null"],"minLength":1,"maxLength":160},"color":{"type":["string","null"],"minLength":1,"maxLength":120},"material":{"type":["string","null"],"minLength":1,"maxLength":120},"visibleText":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":160}},"searchTerms":{"type":"array","minItems":1,"maxItems":30,"items":{"type":"string","minLength":1,"maxLength":160}},"confidence":{"type":"number","minimum":0,"maximum":1}}},"InventoryRecognitionMatch":{"type":"object","additionalProperties":false,"required":["resourceId","confidence","reason","evidence","resource"],"properties":{"resourceId":{"type":"string","format":"uuid"},"confidence":{"type":"number","minimum":0,"maximum":1},"reason":{"type":"string","minLength":1,"maxLength":600},"evidence":{"type":"array","maxItems":8,"items":{"type":"string","minLength":1,"maxLength":240}},"resource":{"$ref":"#/components/schemas/Resource"}}},"InventoryRecognitionResult":{"type":"object","additionalProperties":false,"required":["detected","matches","isConfident","model","catalog"],"properties":{"detected":{"oneOf":[{"$ref":"#/components/schemas/InventoryRecognitionObservation"},{"type":"null"}]},"matches":{"type":"array","maxItems":5,"items":{"$ref":"#/components/schemas/InventoryRecognitionMatch"}},"isConfident":{"type":"boolean","description":"True only when the leading provider score is strong and sufficiently separated from the runner-up; the match remains advisory."},"model":{"type":["string","null"]},"catalog":{"type":"object","additionalProperties":false,"required":["considered","truncated"],"properties":{"considered":{"type":"integer","minimum":0,"maximum":5000},"truncated":{"type":"boolean","description":"True when metadata matches or the image-bearing visual fallback exceeded the bounded comparison catalog; clients should present the result as non-exhaustive."}}}}},"InventoryCountJob":{"type":"object","additionalProperties":false,"required":["status","jobToken","expiresAt"],"properties":{"status":{"type":"string","enum":["processing"]},"jobToken":{"type":"string","minLength":1,"maxLength":4096},"expiresAt":{"type":"string","format":"date-time"},"message":{"type":"string"}}},"ImageGenerationModel":{"type":"object","required":["id","provider","model","label"],"additionalProperties":false,"properties":{"id":{"type":"string","maxLength":240,"example":"google:gemini-3.1-flash-image"},"provider":{"type":"string","enum":["openai","google"]},"model":{"type":"string","maxLength":233,"example":"gemini-3.1-flash-image"},"label":{"type":"string","maxLength":260,"example":"Nano Banana 2"}}},"InventoryCountModel":{"type":"object","required":["id","provider","model","label","description"],"additionalProperties":false,"properties":{"id":{"type":"string","enum":["grounding-dino","yolo-world","sam-2","sam-3"]},"provider":{"type":"string","enum":["replicate"]},"model":{"type":"string","maxLength":240},"label":{"type":"string","maxLength":260},"description":{"type":"string","maxLength":500}}},"BomComponentInput":{"type":"object","required":["resourceId","quantityPerAssembly"],"additionalProperties":false,"properties":{"resourceId":{"type":"string","format":"uuid"},"variantId":{"type":["string","null"],"format":"uuid"},"variantDelta":{"type":["integer","null"]},"variantBalanceAfter":{"type":["integer","null"],"minimum":0},"quantityPerAssembly":{"type":"integer","minimum":1},"position":{"type":"integer","minimum":0},"note":{"type":"string","maxLength":20000}}},"BomComponent":{"allOf":[{"$ref":"#/components/schemas/BomComponentInput"},{"type":"object","required":["id","name","availableQuantity","trackingMode","availableUnits"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"sku":{"type":["string","null"]},"availableQuantity":{"type":"integer","minimum":0},"trackingMode":{"type":"string","enum":["bulk","serialized"]},"availableUnits":{"type":"array","items":{"type":"object","required":["id","code","location"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"location":{"type":["string","null"]}}}}}}]},"BomDetail":{"type":"object","required":["resource","components","buildableQuantity"],"properties":{"resource":{"type":"object","required":["id","name","quantity","trackingMode"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0},"trackingMode":{"type":"string","enum":["bulk","serialized"]}}},"components":{"type":"array","items":{"$ref":"#/components/schemas/BomComponent"}},"buildableQuantity":{"type":"integer","minimum":0}}},"AssemblyBuildInput":{"type":"object","required":["quantity"],"additionalProperties":false,"properties":{"quantity":{"type":"integer","minimum":1,"maximum":1000},"occurredAt":{"type":"string","format":"date-time"},"location":{"type":["string","null"],"maxLength":240},"note":{"type":"string","maxLength":20000},"componentUnitIds":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","format":"uuid"}}},"outputUnitCodes":{"type":"array","items":{"type":"string","maxLength":180}}}},"AssemblyBuild":{"type":"object","required":["id","assemblyResourceId","quantity","occurredAt","createdAt","components","outputUnits"],"properties":{"id":{"type":"string","format":"uuid"},"assemblyResourceId":{"type":"string","format":"uuid"},"quantity":{"type":"integer","minimum":1},"occurredAt":{"type":"string","format":"date-time"},"location":{"type":["string","null"]},"note":{"type":"string"},"createdBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"components":{"type":"array","items":{"type":"object","required":["resourceId","name","sku","quantityPerAssembly","quantityConsumed","componentUnits","stockMovementIds","outputUnitIds"],"properties":{"resourceId":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"sku":{"type":["string","null"]},"quantityPerAssembly":{"type":"integer","minimum":1},"quantityConsumed":{"type":"integer","minimum":1},"componentUnits":{"type":"array","items":{"type":"object","required":["id","code","location","status","outputUnitId"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"location":{"type":["string","null"]},"status":{"type":"string"},"outputUnitId":{"type":["string","null"],"format":"uuid"}}}},"stockMovementIds":{"type":"array","items":{"type":"string","format":"uuid"}},"outputUnitIds":{"type":"array","items":{"type":"string","format":"uuid"}}}}},"outputUnits":{"type":"array","items":{"$ref":"#/components/schemas/StockUnit"}}}},"PurchaseOrderLineInput":{"type":"object","required":["resourceId","orderedQuantity"],"additionalProperties":false,"properties":{"resourceId":{"type":"string","format":"uuid"},"orderedQuantity":{"type":"integer","minimum":1},"expectedAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string","maxLength":20000}}},"PurchaseOrderInput":{"type":"object","required":["lines"],"additionalProperties":false,"properties":{"reference":{"type":["string","null"],"maxLength":160},"supplier":{"type":"string","maxLength":240},"status":{"type":"string","enum":["draft","ordered"]},"orderedAt":{"type":"string","format":"date-time"},"expectedAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string","maxLength":20000},"lines":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/PurchaseOrderLineInput"}}}},"PurchaseOrderLine":{"allOf":[{"$ref":"#/components/schemas/PurchaseOrderLineInput"},{"type":"object","required":["id","resourceName","receivedQuantity","openQuantity","trackingMode"],"properties":{"id":{"type":"string","format":"uuid"},"resourceName":{"type":"string"},"resourceSku":{"type":["string","null"]},"receivedQuantity":{"type":"integer","minimum":0},"openQuantity":{"type":"integer","minimum":0},"trackingMode":{"type":"string","enum":["bulk","serialized"]}}}]},"PurchaseOrder":{"type":"object","required":["id","supplier","status","orderedAt","lines","totalOrdered","totalReceived","totalOpen"],"properties":{"id":{"type":"string","format":"uuid"},"reference":{"type":["string","null"]},"supplier":{"type":"string"},"status":{"type":"string","enum":["draft","ordered","partially-received","received","cancelled"]},"orderedAt":{"type":"string","format":"date-time"},"expectedAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string"},"createdBy":{"type":["string","null"]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrderLine"}},"totalOrdered":{"type":"integer","minimum":0},"totalReceived":{"type":"integer","minimum":0},"totalOpen":{"type":"integer","minimum":0}}},"PurchaseReceiptInput":{"type":"object","required":["quantity"],"additionalProperties":false,"properties":{"quantity":{"type":"integer","minimum":1,"maximum":1000},"receivedAt":{"type":"string","format":"date-time"},"location":{"type":["string","null"],"maxLength":240},"note":{"type":"string","maxLength":20000},"unitCodes":{"type":"array","items":{"type":"string","maxLength":180}}}},"NativeLoginResponse":{"type":"object","required":["token","user","scopes","expiresAt","organization","organizations"],"properties":{"token":{"type":"string","description":"Opaque secret returned only once."},"user":{"type":"object","required":["id","name","email","role"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/AccessRoleKey"}}},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","ai"]}},"expiresAt":{"type":"string","format":"date-time"},"organization":{"$ref":"#/components/schemas/OrganizationMembership"},"organizations":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/OrganizationMembership"}}}},"Pagination":{"type":"object","required":["page","pageSize","total","pages"],"properties":{"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}},"CsvImportResponse":{"type":"object","required":["importId","summary","rows"],"properties":{"importId":{"type":"string","format":"uuid","description":"The request Idempotency-Key."},"summary":{"type":"object","required":["total","created","replayed","failed"],"properties":{"total":{"type":"integer","minimum":1,"maximum":1000},"created":{"type":"integer","minimum":0},"replayed":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}}},"rows":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"object","required":["line","status"],"properties":{"line":{"type":"integer","minimum":2,"description":"One-based source line where the CSV row begins."},"status":{"type":"string","enum":["created","replayed","error"]},"resource":{"type":"object","description":"Present for created and replayed rows.","required":["id","name","sku"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"sku":{"type":["string","null"]}}},"error":{"type":"string","description":"Present for rows with status error."},"details":{"type":"array","items":{"type":"string"}}}}}}},"Media":{"type":"object","required":["id","resourceId","url","name","mimeType","kind","position","source"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"url":{"type":"string"},"name":{"type":"string"},"mimeType":{"type":"string"},"kind":{"type":"string","enum":["image","video","document","model","unknown"]},"position":{"type":"integer"},"source":{"type":"string","enum":["upload","ai"]},"altText":{"type":"string"}}},"ScanWorkflowExtraction":{"oneOf":[{"type":"object","required":["mode"],"additionalProperties":false,"properties":{"mode":{"type":"string","const":"full"}}},{"type":"object","required":["mode","parameter"],"additionalProperties":false,"properties":{"mode":{"type":"string","const":"url-query"},"parameter":{"type":"string","minLength":1,"maxLength":80},"sourceOrigin":{"type":"string","maxLength":300,"description":"Optional exact URL origin; the server never fetches the URL."},"sourcePath":{"type":"string","pattern":"^/[^?#]*$","maxLength":500}}},{"type":"object","required":["mode","prefix"],"additionalProperties":false,"properties":{"mode":{"type":"string","const":"prefix"},"prefix":{"type":"string","minLength":1,"maxLength":160}}}]},"ScanWorkflowFixedProperty":{"type":"object","required":["key","label","value"],"additionalProperties":false,"properties":{"key":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_.-]+$"},"label":{"type":"string","minLength":1,"maxLength":120},"value":{"type":"string","maxLength":240}}},"ScanWorkflowOption":{"type":"object","required":["value","label"],"additionalProperties":false,"properties":{"value":{"type":"string","minLength":1,"maxLength":120},"label":{"type":"string","minLength":1,"maxLength":120},"color":{"type":"string","minLength":1,"maxLength":32}}},"ScanWorkflowInputField":{"type":"object","required":["key","label","required","options"],"additionalProperties":false,"properties":{"key":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_.-]+$"},"label":{"type":"string","minLength":1,"maxLength":120},"required":{"type":"boolean"},"options":{"type":"array","minItems":1,"maxItems":40,"items":{"$ref":"#/components/schemas/ScanWorkflowOption"}}}},"ScanWorkflowInput":{"type":"object","required":["name","resourceId","extraction","identifierPropertyKey"],"properties":{"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","maxLength":5000,"default":""},"enabled":{"type":"boolean","default":true},"resourceId":{"type":"string","format":"uuid"},"extraction":{"$ref":"#/components/schemas/ScanWorkflowExtraction"},"identifierPropertyKey":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_.-]+$"},"createMissingUnit":{"type":"boolean","default":false},"unitStatus":{"oneOf":[{"type":"string","enum":["available","reserved","in-use","maintenance","consumed","lost","retired"]},{"type":"null"}]},"fixedProperties":{"type":"array","maxItems":24,"items":{"$ref":"#/components/schemas/ScanWorkflowFixedProperty"}},"inputFields":{"type":"array","maxItems":12,"items":{"$ref":"#/components/schemas/ScanWorkflowInputField"}}}},"ScanWorkflowPatch":{"type":"object","required":["revision"],"minProperties":2,"additionalProperties":false,"description":"Current revision plus at least one writable ScanWorkflowInput property.","properties":{"revision":{"type":"integer","minimum":1},"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","maxLength":5000},"enabled":{"type":"boolean"},"resourceId":{"type":"string","format":"uuid"},"extraction":{"$ref":"#/components/schemas/ScanWorkflowExtraction"},"identifierPropertyKey":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_.-]+$"},"createMissingUnit":{"type":"boolean"},"unitStatus":{"oneOf":[{"type":"string","enum":["available","reserved","in-use","maintenance","consumed","lost","retired"]},{"type":"null"}]},"fixedProperties":{"type":"array","maxItems":24,"items":{"$ref":"#/components/schemas/ScanWorkflowFixedProperty"}},"inputFields":{"type":"array","maxItems":12,"items":{"$ref":"#/components/schemas/ScanWorkflowInputField"}}}},"ScanWorkflow":{"allOf":[{"$ref":"#/components/schemas/ScanWorkflowInput"},{"type":"object","required":["id","name","description","enabled","resourceId","revision","extraction","identifierPropertyKey","createMissingUnit","unitStatus","fixedProperties","inputFields","createdBy","updatedBy","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"revision":{"type":"integer","minimum":1},"createdBy":{"type":["string","null"]},"updatedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}]},"StockScanResolution":{"type":"object","required":["workflow","resource","identifier","unit","willCreate","fields","fixedProperties","metadataPreview","statusBefore","statusAfter","quantityBefore","quantityAfter","delta","expectedResourceUpdatedAt","expectedUnitId","expectedUnitUpdatedAt"],"additionalProperties":false,"properties":{"workflow":{"$ref":"#/components/schemas/ScanWorkflow"},"resource":{"type":"object","required":["id","name","quantity","trackingMode"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0},"trackingMode":{"type":"string","const":"serialized"}}},"identifier":{"type":"string","minLength":1,"maxLength":180},"unit":{"oneOf":[{"$ref":"#/components/schemas/StockUnit"},{"type":"null"}]},"willCreate":{"type":"boolean"},"statusBefore":{"oneOf":[{"type":"string","enum":["available","reserved","in-use","maintenance","consumed","lost","retired"]},{"type":"null"}]},"statusAfter":{"type":"string","enum":["available","reserved","in-use","maintenance","consumed","lost","retired"]},"quantityBefore":{"type":"integer","minimum":0},"quantityAfter":{"type":"integer","minimum":0},"delta":{"type":"integer","minimum":-1,"maximum":1},"expectedResourceUpdatedAt":{"type":"string","format":"date-time","description":"Resource version captured by resolve; execute rejects a stale quantity preview."},"expectedUnitId":{"description":"Unit captured by resolve, or null when no matching unit existed. Both unit guard fields must be null or non-null together.","oneOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"expectedUnitUpdatedAt":{"description":"Unit version captured by resolve, or null when no matching unit existed. Both unit guard fields must be null or non-null together.","oneOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"fields":{"type":"array","maxItems":12,"items":{"$ref":"#/components/schemas/ScanWorkflowInputField"}},"fixedProperties":{"type":"array","maxItems":24,"items":{"$ref":"#/components/schemas/ScanWorkflowFixedProperty"}},"metadataPreview":{"type":"object","additionalProperties":true}}},"StockScanExecutionInput":{"type":"object","required":["workflowId","revision","code","expectedResourceUpdatedAt","expectedUnitId","expectedUnitUpdatedAt"],"additionalProperties":false,"properties":{"workflowId":{"type":"string","format":"uuid"},"revision":{"type":"integer","minimum":1},"code":{"type":"string","minLength":1,"maxLength":2048},"expectedResourceUpdatedAt":{"type":"string","format":"date-time","description":"Copy exactly from the resolve response."},"expectedUnitId":{"description":"Copy exactly from resolve; must be null together with expectedUnitUpdatedAt or non-null together with it.","oneOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"expectedUnitUpdatedAt":{"description":"Copy exactly from resolve; must be null together with expectedUnitId or non-null together with it.","oneOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"inputs":{"type":"object","default":{},"description":"Operator-provided workflow fields. May be omitted when the workflow has no input fields.","maxProperties":12,"propertyNames":{"minLength":1,"maxLength":80},"additionalProperties":{"type":"string","maxLength":240}}}},"StockScanExecution":{"type":"object","required":["workflowId","revision","resource","unit","movement","created","metadataBefore","metadataAfter"],"additionalProperties":false,"properties":{"workflowId":{"type":"string","format":"uuid"},"revision":{"type":"integer","minimum":1},"resource":{"type":"object","required":["id","name","quantity"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0}}},"unit":{"$ref":"#/components/schemas/StockUnit"},"movement":{"$ref":"#/components/schemas/StockMovement"},"created":{"type":"boolean"},"metadataBefore":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"metadataAfter":{"type":"object","additionalProperties":true}}},"StockLocationResource":{"type":"object","required":["id","name","type","status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"status":{"type":"string","enum":["available","in-use","maintenance","archived"]}}},"StockLocationBalance":{"type":"object","required":["locationResourceId","name","type","quantity"],"properties":{"locationResourceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"quantity":{"type":"integer","minimum":0}}},"StockLocationBreakdown":{"type":"object","required":["resource","trackingMode","assignedQuantity","unassignedQuantity","locations"],"properties":{"resource":{"type":"object","required":["id","name","quantity","trackingMode"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0},"trackingMode":{"type":["string","null"],"enum":["bulk","serialized",null]}}},"trackingMode":{"type":"string","enum":["bulk","serialized"]},"assignedQuantity":{"type":"integer","minimum":0},"unassignedQuantity":{"type":"integer","minimum":0},"locations":{"type":"array","items":{"$ref":"#/components/schemas/StockLocationBalance"}}}},"StockLocationsResponse":{"type":"object","required":["breakdown","availableLocations"],"properties":{"breakdown":{"$ref":"#/components/schemas/StockLocationBreakdown"},"availableLocations":{"type":"array","items":{"$ref":"#/components/schemas/StockLocationResource"}}}},"InventoryCyclePolicyInput":{"type":"object","required":["intervalDays"],"additionalProperties":false,"properties":{"intervalDays":{"type":"integer","minimum":1,"maximum":3650},"enabled":{"type":"boolean","default":true}}},"InventoryCyclePolicy":{"type":"object","required":["resourceId","intervalDays","enabled","nextDueAt","lastCompletedAt","createdBy","updatedBy","createdAt","updatedAt"],"properties":{"resourceId":{"type":"string","format":"uuid"},"intervalDays":{"type":"integer","minimum":1,"maximum":3650},"enabled":{"type":"boolean"},"nextDueAt":{"type":"string","format":"date-time"},"lastCompletedAt":{"type":["string","null"],"format":"date-time"},"createdBy":{"type":["string","null"]},"updatedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"InventoryCountInput":{"type":"object","required":["countedQuantity"],"additionalProperties":false,"properties":{"countedQuantity":{"type":"integer","minimum":0,"maximum":2000000000,"description":"For serialized tracking this must match current availability after individual units have been reviewed or corrected."},"locationResourceId":{"type":["string","null"],"format":"uuid","description":"Reconcile only this structured stock location when provided."},"countedAt":{"type":"string","format":"date-time"},"note":{"type":"string","maxLength":20000}}},"InventoryCountRecord":{"type":"object","required":["id","resourceId","locationResourceId","expectedQuantity","countedQuantity","variance","countedAt","note","movementId","idempotencyKey","createdBy","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"locationResourceId":{"type":["string","null"],"format":"uuid"},"expectedQuantity":{"type":"integer","minimum":0},"countedQuantity":{"type":"integer","minimum":0},"variance":{"type":"integer"},"countedAt":{"type":"string","format":"date-time"},"note":{"type":"string"},"movementId":{"type":["string","null"],"format":"uuid"},"idempotencyKey":{"type":["string","null"],"format":"uuid"},"createdBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"InventoryCountMutation":{"type":"object","required":["count","replayed"],"properties":{"count":{"$ref":"#/components/schemas/InventoryCountRecord"},"movementId":{"type":"string","format":"uuid","description":"Present when the count is newly recorded; replayed counts retain the movement id inside count."},"replayed":{"type":"boolean"}}},"InventoryCycle":{"type":"object","required":["resource","policy","history"],"properties":{"resource":{"type":"object","required":["id","name","quantity","trackingMode"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0},"trackingMode":{"type":"string","enum":["bulk","serialized"]}}},"policy":{"oneOf":[{"$ref":"#/components/schemas/InventoryCyclePolicy"},{"type":"null"}]},"history":{"type":"array","maxItems":25,"items":{"$ref":"#/components/schemas/InventoryCountRecord"}}}},"DueInventoryCycle":{"type":"object","required":["resourceId","name","type","quantity","intervalDays","nextDueAt","lastCompletedAt"],"properties":{"resourceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"quantity":{"type":"integer","minimum":0},"intervalDays":{"type":"integer","minimum":1,"maximum":3650},"nextDueAt":{"type":"string","format":"date-time"},"lastCompletedAt":{"type":["string","null"],"format":"date-time"}}},"InventoryAssignmentRecipientInput":{"oneOf":[{"type":"object","required":["type","userId"],"additionalProperties":false,"properties":{"type":{"type":"string","const":"user"},"userId":{"type":"string","format":"uuid"}}},{"type":"object","required":["type","resourceId"],"additionalProperties":false,"properties":{"type":{"type":"string","const":"resource"},"resourceId":{"type":"string","format":"uuid"}}},{"type":"object","required":["type","label"],"additionalProperties":false,"properties":{"type":{"type":"string","const":"label"},"label":{"type":"string","minLength":1,"maxLength":240}}}],"discriminator":{"propertyName":"type"}},"InventoryAssignmentInput":{"type":"object","required":["kind","recipient"],"additionalProperties":false,"properties":{"kind":{"type":"string","enum":["checkout","assignment","reservation"]},"quantity":{"type":"integer","minimum":1,"maximum":2000000000,"default":1},"stockUnitId":{"type":["string","null"],"format":"uuid","description":"Required for serialized stock and omitted for bulk stock."},"recipient":{"$ref":"#/components/schemas/InventoryAssignmentRecipientInput"},"startsAt":{"type":"string","format":"date-time"},"dueAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string","maxLength":20000}}},"InventoryAssignmentCompletion":{"type":"object","required":["status"],"additionalProperties":false,"properties":{"status":{"type":"string","enum":["returned","cancelled"]},"completedAt":{"type":"string","format":"date-time"},"note":{"type":"string","maxLength":20000}}},"InventoryAssignment":{"type":"object","required":["id","resourceId","stockUnitId","kind","status","quantity","assignee","stockUnit","startsAt","dueAt","completedAt","note","createdBy","completedBy","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"stockUnitId":{"type":["string","null"],"format":"uuid"},"kind":{"type":"string","enum":["checkout","assignment","reservation"]},"status":{"type":"string","enum":["active","returned","cancelled"]},"quantity":{"type":"integer","minimum":1},"assignee":{"type":"object","required":["type","id","label","detail"],"properties":{"type":{"type":"string","enum":["user","resource","label"]},"id":{"type":["string","null"],"format":"uuid"},"label":{"type":"string"},"detail":{"type":["string","null"]}}},"stockUnit":{"oneOf":[{"type":"object","required":["id","code","status"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"status":{"type":["string","null"]}}},{"type":"null"}]},"startsAt":{"type":"string","format":"date-time"},"dueAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"note":{"type":"string"},"createdBy":{"type":["string","null"]},"completedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"InventoryAssignmentMutation":{"type":"object","required":["assignment","resource","movement"],"properties":{"assignment":{"$ref":"#/components/schemas/InventoryAssignment"},"resource":{"type":"object","required":["id","name","quantity"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0}}},"movement":{"$ref":"#/components/schemas/StockMovement"}}},"InventoryAssignmentList":{"type":"object","required":["resource","trackingMode","availability","availableUnits","assignments"],"properties":{"resource":{"type":"object","required":["id","name","quantity"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer","minimum":0}}},"trackingMode":{"type":"string","enum":["bulk","serialized"]},"availability":{"type":"object","required":["availableQuantity","activeQuantity"],"properties":{"availableQuantity":{"type":"integer","minimum":0},"activeQuantity":{"type":"integer","minimum":0}}},"availableUnits":{"type":"array","maxItems":500,"items":{"type":"object","required":["id","code","status","location"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"status":{"type":"string","enum":["available"]},"location":{"type":["string","null"]}}}},"assignments":{"type":"array","maxItems":200,"items":{"$ref":"#/components/schemas/InventoryAssignment"}}}},"StockConfigInput":{"type":"object","properties":{"trackingMode":{"type":"string","enum":["bulk","serialized"]},"minimumStock":{"type":"integer","minimum":0},"reorderQuantity":{"type":"integer","minimum":0},"leadTimeDays":{"type":"integer","minimum":0},"unitName":{"type":"string","minLength":1,"maxLength":80}}},"StockConfig":{"allOf":[{"$ref":"#/components/schemas/StockConfigInput"},{"type":"object","required":["trackingMode","minimumStock","reorderQuantity","leadTimeDays","unitName"]}]},"StockForecast":{"type":"object","required":["averageDailyUsage","daysUntilStockout","predictedStockoutAt","isBelowMinimum","suggestedReorderQuantity"],"properties":{"averageDailyUsage":{"type":["number","null"],"minimum":0},"daysUntilStockout":{"type":["number","null"],"minimum":0},"predictedStockoutAt":{"type":["string","null"],"format":"date-time"},"isBelowMinimum":{"type":"boolean"},"suggestedReorderQuantity":{"type":"integer","minimum":0}}},"StockMovementInput":{"type":"object","required":["delta","type"],"additionalProperties":false,"properties":{"delta":{"type":"integer","minimum":-2000000000,"maximum":2000000000,"description":"Positive receipts and negative issues. Structured transfers require zero because the global balance does not change."},"quantity":{"type":"integer","minimum":0,"maximum":2000000000,"description":"Required and positive for a structured transfer; otherwise it must equal the absolute delta when provided."},"type":{"type":"string","enum":["receipt","issue","adjustment","return","waste","transfer"]},"reason":{"type":["string","null"],"maxLength":240},"note":{"type":"string","maxLength":20000},"location":{"type":["string","null"],"maxLength":240},"fromLocationResourceId":{"type":["string","null"],"format":"uuid","description":"Structured source location for an issue or transfer."},"toLocationResourceId":{"type":["string","null"],"format":"uuid","description":"Structured destination location for a receipt or transfer."},"occurredAt":{"type":"string","format":"date-time"}}},"StockMovement":{"type":"object","required":["id","resourceId","delta","quantity","balanceAfter","fromLocationBalanceAfter","toLocationBalanceAfter","type","note","location","fromLocationResourceId","toLocationResourceId","occurredAt","createdAt","createdBy"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"unitId":{"type":["string","null"],"format":"uuid"},"assemblyBuildId":{"type":["string","null"],"format":"uuid"},"purchaseReceiptId":{"type":["string","null"],"format":"uuid"},"delta":{"type":"integer"},"quantity":{"type":"integer","minimum":0},"balanceAfter":{"type":"integer","minimum":0},"fromLocationBalanceAfter":{"type":["integer","null"],"minimum":0},"toLocationBalanceAfter":{"type":["integer","null"],"minimum":0},"type":{"type":"string","description":"Includes client booking types plus system audit types such as opening_balance, inventory-count, assignment-checkout, assignment-return, unit-created, unit-status, and merge."},"reason":{"type":["string","null"]},"note":{"type":"string"},"location":{"type":["string","null"]},"fromLocationResourceId":{"type":["string","null"],"format":"uuid"},"toLocationResourceId":{"type":["string","null"],"format":"uuid"},"occurredAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":["string","null"]}}},"StockUnitInput":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":100,"default":1},"code":{"type":"string","maxLength":180},"codes":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":180}},"location":{"type":["string","null"],"maxLength":240},"locationResourceId":{"type":["string","null"],"format":"uuid"},"metadata":{"type":"object","additionalProperties":true},"customFields":{"$ref":"#/components/schemas/CustomFieldValues"},"acquiredAt":{"type":"string","format":"date-time"}}},"StockUnitPatch":{"type":"object","properties":{"status":{"type":"string","enum":["available","reserved","in-use","maintenance","consumed","lost","retired"]},"location":{"type":["string","null"],"maxLength":240},"locationResourceId":{"type":["string","null"],"format":"uuid"},"metadata":{"type":"object","additionalProperties":true},"customFields":{"$ref":"#/components/schemas/CustomFieldValues"},"occurredAt":{"type":"string","format":"date-time"},"reason":{"type":["string","null"],"maxLength":240},"note":{"type":"string","maxLength":20000}}},"StockUnit":{"allOf":[{"$ref":"#/components/schemas/StockUnitPatch"},{"type":"object","required":["id","resourceId","code","status","location","locationResourceId","metadata","customFields","acquiredAt","lastMovedAt","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"code":{"type":"string"},"acquiredAt":{"type":"string","format":"date-time"},"lastMovedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}]},"StockOverviewItem":{"type":"object","required":["resourceId","name","type","quantity","onOrder","projectedQuantity","minimumStock","trackingMode","reorderSuggested","unitName"],"properties":{"resourceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string"},"quantity":{"type":"integer","minimum":0},"onOrder":{"type":"integer","minimum":0},"projectedQuantity":{"type":"integer","minimum":0},"nextExpectedAt":{"type":["string","null"],"format":"date-time"},"minimumStock":{"type":"integer","minimum":0},"trackingMode":{"type":"string","enum":["bulk","serialized"]},"averageDailyUsage":{"type":["number","null"],"minimum":0},"daysUntilStockout":{"type":["number","null"],"minimum":0},"predictedStockoutAt":{"type":["string","null"],"format":"date-time"},"reorderSuggested":{"type":"boolean"},"unitName":{"type":"string"}}},"StockDetail":{"type":"object","required":["resource","config","forecast","procurement","movements","units"],"properties":{"resource":{"type":"object","required":["id","name","type","categories","quantity"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"categories":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"color":{"type":"string"}}}},"quantity":{"type":"integer","minimum":0}}},"config":{"$ref":"#/components/schemas/StockConfig"},"forecast":{"$ref":"#/components/schemas/StockForecast"},"procurement":{"type":"object","required":["onOrder","projectedQuantity","nextExpectedAt","openLines"],"properties":{"onOrder":{"type":"integer","minimum":0},"projectedQuantity":{"type":"integer","minimum":0},"nextExpectedAt":{"type":["string","null"],"format":"date-time"},"openLines":{"type":"array","items":{"type":"object","required":["lineId","orderId","supplier","orderedQuantity","receivedQuantity","openQuantity"],"properties":{"lineId":{"type":"string","format":"uuid"},"orderId":{"type":"string","format":"uuid"},"reference":{"type":["string","null"]},"supplier":{"type":"string"},"orderedQuantity":{"type":"integer","minimum":1},"receivedQuantity":{"type":"integer","minimum":0},"openQuantity":{"type":"integer","minimum":1},"expectedAt":{"type":["string","null"],"format":"date-time"}}}}}},"movements":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/StockMovement"}},"units":{"type":"array","items":{"$ref":"#/components/schemas/StockUnit"}}}},"ResourceInput":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":240},"description":{"type":"string","maxLength":20000},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"status":{"type":"string","enum":["available","in-use","maintenance","archived"]},"sku":{"type":["string","null"],"maxLength":80},"barcode":{"type":["string","null"],"maxLength":180},"quantity":{"type":"integer","minimum":0,"description":"Opening quantity; later changes use stock movements."},"location":{"type":["string","null"]},"serialNumber":{"type":["string","null"]},"valueCents":{"type":["integer","null"],"minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"priority":{"type":"integer","minimum":1,"maximum":5},"tags":{"type":"array","items":{"type":"string"}},"categories":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"color":{"type":"string"}}}},"relatedResourceIds":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid"},"description":"Legacy undirected related-item ids. Prefer typed resource relationships for new integrations."},"gpsLatitude":{"type":["number","null"],"minimum":-90,"maximum":90},"gpsLongitude":{"type":["number","null"],"minimum":-180,"maximum":180},"gpsAltitude":{"type":["number","null"]},"mapFeatures":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ResourceMapFeature"}},"notes":{"type":"string"},"customFields":{"$ref":"#/components/schemas/CustomFieldValues"}}},"ResourcePatch":{"type":"object","description":"Any subset of the writable resource fields.","properties":{"name":{"type":"string","minLength":1,"maxLength":240},"description":{"type":"string","maxLength":20000},"type":{"$ref":"#/components/schemas/InventoryTypeKey"},"status":{"type":"string","enum":["available","in-use","maintenance","archived"]},"sku":{"type":["string","null"],"maxLength":80},"barcode":{"type":["string","null"],"maxLength":180},"location":{"type":["string","null"]},"serialNumber":{"type":["string","null"]},"valueCents":{"type":["integer","null"],"minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"priority":{"type":"integer","minimum":1,"maximum":5},"tags":{"type":"array","items":{"type":"string"}},"categories":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"color":{"type":"string"}}}},"relatedResourceIds":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid"},"description":"Legacy undirected related-item ids. Prefer typed resource relationships for new integrations."},"gpsLatitude":{"type":["number","null"],"minimum":-90,"maximum":90},"gpsLongitude":{"type":["number","null"],"minimum":-180,"maximum":180},"gpsAltitude":{"type":["number","null"]},"mapFeatures":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ResourceMapFeature"}},"notes":{"type":"string"},"customFields":{"$ref":"#/components/schemas/CustomFieldValues"}}},"ResourceVariantInput":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":240},"sku":{"type":["string","null"],"maxLength":80},"barcode":{"type":["string","null"],"maxLength":180},"priceCents":{"type":["integer","null"],"minimum":0,"maximum":2000000000},"currency":{"type":"string","minLength":3,"maxLength":3},"position":{"type":"integer","minimum":0,"maximum":100000},"initialAllocation":{"type":"integer","minimum":0,"maximum":2000000000,"default":0}}},"ResourceVariantPatch":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":240},"sku":{"type":["string","null"],"maxLength":80},"barcode":{"type":["string","null"],"maxLength":180},"priceCents":{"type":["integer","null"],"minimum":0,"maximum":2000000000},"currency":{"type":"string","minLength":3,"maxLength":3},"position":{"type":"integer","minimum":0,"maximum":100000}}},"ResourceVariant":{"type":"object","required":["id","resourceId","name","currency","quantity","position","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"sku":{"type":["string","null"]},"barcode":{"type":["string","null"]},"priceCents":{"type":["integer","null"],"minimum":0},"currency":{"type":"string"},"quantity":{"type":"integer","minimum":0},"position":{"type":"integer","minimum":0},"createdBy":{"type":["string","null"]},"updatedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ResourceVariantStockSummary":{"type":"object","required":["totalQuantity","allocatedQuantity","unallocatedQuantity","variantCount"],"properties":{"totalQuantity":{"type":"integer","minimum":0},"allocatedQuantity":{"type":"integer","minimum":0},"unallocatedQuantity":{"type":"integer","minimum":0},"variantCount":{"type":"integer","minimum":0}}},"ResourceVariantStockMovementInput":{"type":"object","additionalProperties":false,"required":["delta"],"properties":{"delta":{"type":"integer","minimum":-2000000000,"maximum":2000000000,"not":{"const":0}},"type":{"type":"string","enum":["receipt","issue","adjustment","return","waste"],"default":"adjustment"},"reason":{"type":["string","null"],"maxLength":240},"note":{"type":"string","maxLength":20000},"occurredAt":{"type":"string","format":"date-time"}}},"ResourceMapFeature":{"type":"object","required":["id","type","layer","description","coordinates"],"properties":{"id":{"type":"string","minLength":1,"maxLength":80},"type":{"type":"string","enum":["point","polygon"]},"layer":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":5000},"coordinates":{"description":"A [longitude, latitude] pair for points or a closed ring of pairs for polygons.","oneOf":[{"type":"array","minItems":2,"maxItems":2,"items":{"type":"number"}},{"type":"array","minItems":4,"maxItems":500,"items":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"number"}}}]}}},"Resource":{"allOf":[{"$ref":"#/components/schemas/ResourceInput"},{"type":"object","required":["id","customFields","createdAt","updatedAt","media"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"media":{"type":"array","items":{"$ref":"#/components/schemas/Media"}},"cover":{"oneOf":[{"$ref":"#/components/schemas/Media"},{"type":"null"}]}}}]}}}}