{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.32.0","description":"Platform API: verified identities, RBAC/scopes, request governance, transactional webhooks, CAT-1 catalog and PRICE-1 lists/variant prices. API-key reads require opt-in PUBLIC lists and currently effective prices under active published products. Amounts are exact decimal strings. INV-1 adds warehouses, immutable quantity/reservation ledgers, derived stock and safe public availability; INV-2 adds permanent serial/IMEI identities, versioned unit/reservation ledgers and explicit serial-read scope. Public availability includes serialized units without exposing identifiers or internal locations. SALES-1 adds private customers, versioned sales orders, exact price snapshots, inventory reservations, complete delivery and cancellation before delivery. POS-1 adds human-operated registers, cash sessions and immutable cash receipts with atomic Sales delivery. Money is exact; unsupported precision is rejected without rounding. OPS-2 adds human-only quotations (proposals with a price snapshot and no inventory effect), a commercial view of sales reservations and transfer orders within one legal entity with transit custody. OPS-3 adds human-only commercial invoices for both sides, payments with partial applications, credits that are balances only once recognised, refunds and physical supplier returns; balances are derived from applications, a register receipt settles its invoice once, and nothing here is a fiscal document. OPS-4 adds human-only import orders between legal entities of one tenant, where exactly one ledger movement crosses entities and units keep their identity, and read-only reports for stock, goods in transit and receivable/payable balances. ACCOUNTING-1 adds a human-only double-entry ledger per legal entity (chart of accounts, mappings, fiscal periods, journal, general ledger, trial balance, reconciliation, settlements); once an entity keeps books every covered operation posts its entry in the same transaction or fails. VAL-1 values inventory per entity and variant with moving weighted average or FIFO layers from real costs only. PAY-1 adds payment components to counter collections and payments (cash, transfer, debit/credit card, cheque, other; pending and confirmed), cash movements and card settlements; no acquirer is contacted and no card number is stored. INVOICE-IMEI-1 lets an invoice carry the physical units of its serialized lines and be confirmed together with its receipt or its delivery in one transaction, through the purchase or the sale it writes, and adds the traceability of one unit with its documents filtered by the read permission of each module. INVOICE-IMEI-2 makes a device be received with the condition and grade its SKU proposes or the ones stated for it (never assumed new), lets a person holding sales.price.override agree a sale price other than the list price, kept as a snapshot from the quotation to the order, the invoice and the register, and names on the records of transfer, import and sales orders the units each one moved. ONBOARDING-1 adds verified human self-service setup of a new company, explicit fiscal dates, valuation defaults and the approved plan catalog. Setup is atomic and durably idempotent; selecting a paid plan leaves it pending with FREE effective limits until billing is implemented. CONTACTS-1 adds an optional extended profile to customers and suppliers (identification, primary contact, billing and shipping addresses, contact persons, commercial notes, tags and custom fields): descriptive data that grants no credit and computes no charge or tax; requests without it behave as before."},"servers":[{"url":"https://api.marky.ec/v1"}],"paths":{"/health":{"get":{"operationId":"health","security":[],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status","service"],"properties":{"status":{"const":"ok"},"service":{"const":"api"}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth or database unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/ready":{"get":{"operationId":"readiness","security":[],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status","service","database"],"properties":{"status":{"const":"ok"},"service":{"const":"api"},"database":{"const":"ready"}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth or database unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/openapi.json":{"get":{"operationId":"openapi","security":[],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"}},"content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth or database unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/auth/me":{"get":{"operationId":"currentUser","security":[{"SupabaseBearer":[]}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentUser"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/context":{"get":{"operationId":"tenantContext","security":[{"SupabaseBearer":[]}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizedUserContext"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"description":"Candidate UUIDv7, authorized against live membership","schema":{"type":"string","format":"uuid"}}]}},"/tenants/{tenantId}/iam/permissions":{"get":{"operationId":"permissionCatalog","security":[{"SupabaseBearer":[]}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["permissions"],"properties":{"permissions":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string"}}}}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"description":"Candidate UUIDv7, authorized against live membership","schema":{"type":"string","format":"uuid"}}],"description":"Requires users.manage in this tenant, checked again inside the write transaction."}},"/tenants/{tenantId}/iam/commands":{"post":{"operationId":"manageIam","security":[{"SupabaseBearer":[]}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"},"description":"Server-generated UUIDv7"},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id"],"properties":{"id":{"type":"string","format":"uuid"}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"description":"Candidate UUIDv7, authorized against live membership","schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"description":"Requires users.manage in this tenant, checked again inside the write transaction.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["kind","code","name"],"properties":{"kind":{"const":"create_role"},"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"name":{"type":"string","minLength":1,"maxLength":200}}},{"type":"object","additionalProperties":false,"required":["kind","roleId","status"],"properties":{"kind":{"const":"set_role_status"},"roleId":{"type":"string","format":"uuid"},"status":{"enum":["ACTIVE","DISABLED"]}}},{"type":"object","additionalProperties":false,"required":["kind","roleId","permissions"],"properties":{"kind":{"const":"replace_role_permissions"},"roleId":{"type":"string","format":"uuid"},"permissions":{"type":"array","uniqueItems":true,"maxItems":21,"items":{"type":"string","enum":["catalog.read","catalog.write","inventory.read","inventory.adjust","inventory.transfer","inventory.serials.read","pricing.read","pricing.write","purchases.read","purchases.create","purchases.approve","sales.read","sales.create","sales.cancel","customers.read","customers.write","reports.cost.read","reports.margin.read","api.manage","users.manage","settings.manage"]}}}},{"type":"object","additionalProperties":false,"required":["kind","userId"],"properties":{"kind":{"const":"create_membership"},"userId":{"type":"string","format":"uuid"}}},{"type":"object","additionalProperties":false,"required":["kind","membershipId","status"],"properties":{"kind":{"const":"set_membership_status"},"membershipId":{"type":"string","format":"uuid"},"status":{"enum":["ACTIVE","SUSPENDED"]}}},{"type":"object","additionalProperties":false,"required":["kind","membershipId","roleId"],"properties":{"kind":{"const":"assign_role"},"membershipId":{"type":"string","format":"uuid"},"roleId":{"type":"string","format":"uuid"}}},{"type":"object","additionalProperties":false,"required":["kind","membershipId","roleId"],"properties":{"kind":{"const":"revoke_role"},"membershipId":{"type":"string","format":"uuid"},"roleId":{"type":"string","format":"uuid"}}}]}}}}}},"/tenants/{tenantId}/api-clients":{"get":{"operationId":"listApiClients","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApiClient"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"post":{"operationId":"createApiClient","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","environment","scopes"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"environment":{"enum":["test","live"]},"scopes":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","enum":["catalog.read","catalog.write","pricing.read","pricing.write","inventory.read","inventory.serials.read","inventory.write","customers.read","customers.write","suppliers.read","suppliers.write","purchases.read","purchases.write","sales.read","sales.write","webhooks.manage"]}}}}}}}}},"/tenants/{tenantId}/api-clients/scopes":{"get":{"operationId":"listApiScopes","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["scopes"],"properties":{"scopes":{"type":"array","items":{"type":"string","enum":["catalog.read","catalog.write","pricing.read","pricing.write","inventory.read","inventory.serials.read","inventory.write","customers.read","customers.write","suppliers.read","suppliers.write","purchases.read","purchases.write","sales.read","sales.write","webhooks.manage"]}}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/tenants/{tenantId}/api-clients/{clientId}/status":{"patch":{"operationId":"setApiClientStatus","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status"],"properties":{"status":{"enum":["ACTIVE","DISABLED"]}}}}}}}},"/tenants/{tenantId}/api-clients/{clientId}/scopes":{"put":{"operationId":"replaceApiClientScopes","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["scopes"],"properties":{"scopes":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","enum":["catalog.read","catalog.write","pricing.read","pricing.write","inventory.read","inventory.serials.read","inventory.write","customers.read","customers.write","suppliers.read","suppliers.write","purchases.read","purchases.write","sales.read","sales.write","webhooks.manage"]}}}}}}}}},"/tenants/{tenantId}/api-clients/{clientId}/keys":{"get":{"operationId":"listApiKeys","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyMetadata"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"post":{"operationId":"issueApiKey","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedApiKey"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["expiresAt"],"properties":{"expiresAt":{"type":"string","format":"date-time","description":"Required future UTC Z timestamp; seconds or 3-digit milliseconds. Immutable after issuance."}}}}}}}},"/tenants/{tenantId}/api-clients/{clientId}/keys/{keyId}/revoke":{"post":{"operationId":"revokeApiKey","security":[{"SupabaseBearer":[]}],"description":"Requires USER with current api.manage in this tenant; checks repeat in the same management transaction.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"description":"Present and true only when replaying a completed non-secret response.","schema":{"const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyMetadata"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Business conflict, fingerprint conflict, expired key or credential response already delivered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"keyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"UUIDv4/UUIDv7. Scoped by tenant, USER/API_CLIENT and operation. 24h TTL; changed fingerprint gives 409. Expired records are tombstones. Credential issuance cannot replay its secret.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[47][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}}},"/api-client/context":{"get":{"operationId":"apiClientContext","security":[{"PlatformApiKey":[]}],"description":"Requires catalog.read. Tenant and scopes come from the verified key.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClientContext"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["catalog.read"]}},"/tenants/{tenantId}/audit":{"get":{"operationId":"listAudit","description":"USER with active membership and settings.manage, rechecked in the read transaction. API_CLIENT cannot read audit. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","security":[{"SupabaseBearer":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Newest events by UUIDv7 cursor within authorized tenant","headers":{"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditPage"}}}},"400":{"description":"Safe Problem Details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Safe Problem Details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Safe Problem Details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Safe Problem Details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"schema":{"type":"integer","minimum":1}}}},"503":{"description":"Safe Problem Details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/webhooks":{"get":{"operationId":"tenantWebhookList","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"post":{"operationId":"tenantWebhookCreate","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant. Idempotency-Key required. Credential responses are available once; retry returns 409.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCredential"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}}}},"/tenants/{tenantId}/webhooks/{endpointId}":{"patch":{"operationId":"tenantWebhookUpdate","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant. Idempotency-Key required; atomic effects/response/audit.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}}}},"/tenants/{tenantId}/webhooks/{endpointId}/rotate-secret":{"post":{"operationId":"tenantWebhookRotatesecret","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant. Idempotency-Key required. Credential responses are available once; retry returns 409.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCredential"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}}},"/tenants/{tenantId}/webhooks/{endpointId}/test":{"post":{"operationId":"tenantWebhookTest","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant. Idempotency-Key required; atomic effects/response/audit.","responses":{"202":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}}},"/tenants/{tenantId}/webhooks/{endpointId}/deliveries":{"get":{"operationId":"tenantWebhookDeliveries","security":[{"SupabaseBearer":[]}],"description":"Requires USER api.manage in current tenant.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}]}},"/api-client/webhooks":{"get":{"operationId":"apiClientWebhookList","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[]},"post":{"operationId":"apiClientWebhookCreate","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key. Idempotency-Key required. Credential responses are available once; retry returns 409.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCredential"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}}}},"/api-client/webhooks/{endpointId}":{"patch":{"operationId":"apiClientWebhookUpdate","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key. Idempotency-Key required; atomic effects/response/audit.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}}}},"/api-client/webhooks/{endpointId}/rotate-secret":{"post":{"operationId":"apiClientWebhookRotatesecret","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key. Idempotency-Key required. Credential responses are available once; retry returns 409.","responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCredential"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}}},"/api-client/webhooks/{endpointId}/test":{"post":{"operationId":"apiClientWebhookTest","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key. Idempotency-Key required; atomic effects/response/audit.","responses":{"202":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7, 24-hour replay window; no plaintext credentials in records."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}}},"/api-client/webhooks/{endpointId}/deliveries":{"get":{"operationId":"apiClientWebhookDeliveries","security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT webhooks.manage, PUBLIC_API entitlement; tenant derives from key.","responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}]}},"/tenants/{tenantId}/catalog/products":{"get":{"operationId":"tenantCatalogListProducts","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected.  Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"publicationStatus","in":"query","schema":{"enum":["DRAFT","PUBLISHED"]}},{"name":"categoryId","in":"query","description":"Only products classified under this category of the same tenant.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"brandId","in":"query","description":"Only products of this brand of the same tenant.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"manufacturerId","in":"query","description":"Only products of this manufacturer of the same tenant.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"name","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"description","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"skuContains","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"barcodeContains","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"modelNumber","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"serialNumber","in":"query","required":false,"schema":{"type":"string","maxLength":100,"description":"Requires inventory.read and inventory.serials.read; warehouse RLS applies."}},{"name":"tracking","in":"query","required":false,"schema":{"enum":["NONE","QUANTITY","SERIALIZED"]}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","ARCHIVED","ALL"]}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantCatalogCreateProduct","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Create in DRAFT; publish by PUT after an active variant exists. Type, unit and tracking become immutable once any variant exists. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductCreated"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductCreateInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}":{"get":{"operationId":"tenantCatalogGetProduct","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantCatalogUpdateProduct","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires catalog.write. Edits article data; archived articles may update only general metadata (name, classification, descriptions and attributes). Status, archive date, publication, identifiers, type, unit, tracking and variant mode stay fixed. Forbidden archived configuration changes return ARCHIVED_PRODUCT_CONFIGURATION_LOCKED (409). Active inventory goods may switch quantity/serialized tracking only when no variant has documents, inventory or valuation references; otherwise TRACKING_HAS_TRANSACTIONS (409). Existing transaction snapshots stay intact.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductInput"}}}}},"delete":{"operationId":"tenantCatalogDeleteProduct","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires catalog.write. Permanently deletes an article and its variants only when no transaction references them, including drafts and cancelled documents. Configuration media/prices and the derived search projection are removed atomically; transactional history is never deleted. ARTICLE_HAS_TRANSACTIONS returns 409. SKUs of deleted unused articles can be reused; SKUs of existing archived articles remain unique. Idempotency-Key is required and successful deletions replay safely.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string","format":"uuid"},"deleted":{"const":true}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/archive":{"post":{"operationId":"tenantCatalogArchiveProduct","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Parent becomes ARCHIVED/DRAFT; descendant records and reserved SKUs remain stored and no longer appear in storefront reads. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/variants":{"get":{"operationId":"tenantCatalogListVariants","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}},{"name":"sku","in":"query","schema":{"type":"string","maxLength":100}},{"name":"barcode","in":"query","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariantPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantCatalogCreateVariant","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariantInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/variants/{id}":{"put":{"operationId":"tenantCatalogUpdateVariant","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariantInput"}}}}},"get":{"operationId":"tenantCatalogGetVariant","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/variants/{id}/archive":{"post":{"operationId":"tenantCatalogArchiveVariant","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Final active variant of a published product cannot be archived; unpublish first. SKU remains reserved forever. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/media":{"get":{"operationId":"tenantCatalogListMedia","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMediaPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantCatalogCreateMedia","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMediaInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/media/{id}":{"put":{"operationId":"tenantCatalogUpdateMedia","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMediaInput"}}}}}},"/tenants/{tenantId}/catalog/products/{productId}/media/{id}/archive":{"post":{"operationId":"tenantCatalogArchiveMedia","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/tenants/{tenantId}/catalog/lookups/{kind}":{"get":{"operationId":"tenantCatalogListLookups","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.read in the requested tenant. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnionPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantCatalogCreateLookup","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnionInput"}}}}}},"/tenants/{tenantId}/catalog/lookups/{kind}/{id}":{"put":{"operationId":"tenantCatalogUpdateLookup","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnionInput"}}}}}},"/tenants/{tenantId}/catalog/lookups/{kind}/{id}/archive":{"post":{"operationId":"tenantCatalogArchiveLookup","tags":["Catalog"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER catalog.write in the requested tenant. Conflicts while referenced by an active product. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/api-client/catalog/products":{"get":{"operationId":"apiClientCatalogListProducts","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. ","parameters":[{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE"],"default":"ACTIVE"}},{"name":"publicationStatus","in":"query","schema":{"enum":["PUBLISHED"]}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogProductPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"apiClientCatalogCreateProduct","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Create in DRAFT; publish by PUT after an active variant exists. Type, unit and tracking become immutable once any variant exists. ","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogProductCreated"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductCreateInput"}}}}}},"/api-client/catalog/products/{productId}":{"get":{"operationId":"apiClientCatalogGetProduct","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"apiClientCatalogUpdateProduct","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires catalog.write. Edits article data; archived articles may update only general metadata (name, classification, descriptions and attributes). Status, archive date, publication, identifiers, type, unit, tracking and variant mode stay fixed. Forbidden archived configuration changes return ARCHIVED_PRODUCT_CONFIGURATION_LOCKED (409). Active inventory goods may switch quantity/serialized tracking only when no variant has documents, inventory or valuation references; otherwise TRACKING_HAS_TRANSACTIONS (409). Existing transaction snapshots stay intact.","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogProductInput"}}}}},"delete":{"operationId":"apiClientCatalogDeleteProduct","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires catalog.write. Permanently deletes an article and its variants only when no transaction references them, including drafts and cancelled documents. Configuration media/prices and the derived search projection are removed atomically; transactional history is never deleted. ARTICLE_HAS_TRANSACTIONS returns 409. SKUs of deleted unused articles can be reused; SKUs of existing archived articles remain unique. Idempotency-Key is required and successful deletions replay safely.","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string","format":"uuid"},"deleted":{"const":true}}}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/api-client/catalog/products/{productId}/archive":{"post":{"operationId":"apiClientCatalogArchiveProduct","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Parent becomes ARCHIVED/DRAFT; descendant records and reserved SKUs remain stored and no longer appear in storefront reads. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogProduct"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/api-client/catalog/products/{productId}/variants":{"get":{"operationId":"apiClientCatalogListVariants","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE"],"default":"ACTIVE"}},{"name":"sku","in":"query","schema":{"type":"string","maxLength":100}},{"name":"barcode","in":"query","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogVariantPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"apiClientCatalogCreateVariant","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariantInput"}}}}}},"/api-client/catalog/products/{productId}/variants/{id}":{"put":{"operationId":"apiClientCatalogUpdateVariant","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogVariantInput"}}}}},"get":{"operationId":"apiClientCatalogGetVariant","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api-client/catalog/products/{productId}/variants/{id}/archive":{"post":{"operationId":"apiClientCatalogArchiveVariant","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Final active variant of a published product cannot be archived; unpublish first. SKU remains reserved forever. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogVariant"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/api-client/catalog/products/{productId}/media":{"get":{"operationId":"apiClientCatalogListMedia","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogMediaPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"apiClientCatalogCreateMedia","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMediaInput"}}}}}},"/api-client/catalog/products/{productId}/media/{id}":{"put":{"operationId":"apiClientCatalogUpdateMedia","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogMediaInput"}}}}}},"/api-client/catalog/products/{productId}/media/{id}/archive":{"post":{"operationId":"apiClientCatalogArchiveMedia","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. URL metadata only; no fetch or storage provisioning. Pagination is by id; position is display metadata. ","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogMedia"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/api-client/catalog/lookups/{kind}":{"get":{"operationId":"apiClientCatalogListLookups","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.read and PUBLIC_API entitlement. Tenant is derived from the key. Cursor pagination ordered by UUIDv7 ascending, max 100. Unknown query parameters rejected. Products must be ACTIVE/PUBLISHED; variants/media ACTIVE under a published parent. Free attributes and internal tracking fields omitted. ","parameters":[{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","schema":{"enum":["ACTIVE"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogLookupUnionPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"apiClientCatalogCreateLookup","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. ","parameters":[{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnionInput"}}}}}},"/api-client/catalog/lookups/{kind}/{id}":{"put":{"operationId":"apiClientCatalogUpdateLookup","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Full replacement of editable fields; omitted optional fields reset to defaults/null. SKU and lookup codes immutable; archived records cannot be edited. ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnionInput"}}}}}},"/api-client/catalog/lookups/{kind}/{id}/archive":{"post":{"operationId":"apiClientCatalogArchiveLookup","tags":["Catalog"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT catalog.write and PUBLIC_API entitlement. Tenant is derived from the key. Conflicts while referenced by an active product. ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["brands","categories","manufacturers","units"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogLookupUnion"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Conflict or last manager","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCatalogInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists":{"get":{"operationId":"tenantPricingListLists","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.read, active membership and current tenant permission. Human reads include internal lists and history. Prices default ACTIVE across all periods; at filters validity. Cursor UUIDv7 ascending, default 50/max 100; unknown queries rejected.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}},{"name":"visibility","in":"query","required":false,"schema":{"enum":["INTERNAL","PUBLIC"]}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPricingCreateList","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}":{"get":{"operationId":"tenantPricingGetList","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.read, active membership and current tenant permission. Human reads include internal lists and history. Prices default ACTIVE across all periods; at filters validity. Cursor UUIDv7 ascending, default 50/max 100; unknown queries rejected.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantPricingUpdateList","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}/archive":{"post":{"operationId":"tenantPricingArchiveList","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Archive is permanent; descendants/history retained and list code reserved. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyPricingInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}/prices":{"get":{"operationId":"tenantPricingListPrices","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.read, active membership and current tenant permission. Human reads include internal lists and history. Prices default ACTIVE across all periods; at filters validity. variantIds reads the prices of up to 100 variants of this company in one request and cannot be combined with variantId; ids of other companies match nothing. Cursor UUIDv7 ascending, default 50/max 100; unknown queries rejected.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantIds","in":"query","required":false,"schema":{"type":"string","description":"Human reads only. 1 to 100 distinct UUIDv7 variant ids separated by commas; repeated or malformed ids, more than 100, or variantId in the same request are rejected with 400."}},{"name":"at","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricePage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPricingCreatePrice","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}/prices/{id}":{"get":{"operationId":"tenantPricingGetPrice","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.read, active membership and current tenant permission. Human reads include internal lists and history. Prices default ACTIVE across all periods; at filters validity. Cursor UUIDv7 ascending, default 50/max 100; unknown queries rejected.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantPricingUpdatePrice","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}/prices/{id}/archive":{"post":{"operationId":"tenantPricingArchivePrice","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.write, active membership and current tenant permission. Archived price cannot be restored or edited; frees its active validity interval. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyPricingInput"}}}}}},"/tenants/{tenantId}/pricing/price-lists/{listId}/resolve/{variantId}":{"get":{"operationId":"tenantPricingResolvePrice","tags":["Pricing"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER pricing.read, active membership and current tenant permission. Resolve exactly one ACTIVE price at the database statement time (optional UTC at for humans only). Missing effective price returns 404; no fallback list, discount, tax, conversion or rounding. Human reads include internal lists and history. Prices default ACTIVE across all periods; at filters validity. Cursor UUIDv7 ascending, default 50/max 100; unknown queries rejected.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"at","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api-client/pricing/price-lists":{"get":{"operationId":"apiClientPricingListLists","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.read and PUBLIC_API entitlement; tenant is derived from the verified key. API-key reads expose ACTIVE/PUBLIC lists and ACTIVE currently effective prices for ACTIVE variants under ACTIVE/PUBLISHED products. Internal description and tenant/archive fields omitted; historical at and ARCHIVED/INTERNAL filters rejected.","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE"],"default":"ACTIVE"}},{"name":"visibility","in":"query","required":false,"schema":{"enum":["PUBLIC"]}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPriceListPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.read"]},"post":{"operationId":"apiClientPricingCreateList","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListInput"}}}}}},"/api-client/pricing/price-lists/{listId}":{"get":{"operationId":"apiClientPricingGetList","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.read and PUBLIC_API entitlement; tenant is derived from the verified key. API-key reads expose ACTIVE/PUBLIC lists and ACTIVE currently effective prices for ACTIVE variants under ACTIVE/PUBLISHED products. Internal description and tenant/archive fields omitted; historical at and ARCHIVED/INTERNAL filters rejected.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.read"]},"put":{"operationId":"apiClientPricingUpdateList","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListInput"}}}}}},"/api-client/pricing/price-lists/{listId}/archive":{"post":{"operationId":"apiClientPricingArchiveList","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Archive is permanent; descendants/history retained and list code reserved. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPriceList"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyPricingInput"}}}}}},"/api-client/pricing/price-lists/{listId}/prices":{"get":{"operationId":"apiClientPricingListPrices","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.read and PUBLIC_API entitlement; tenant is derived from the verified key. API-key reads expose ACTIVE/PUBLIC lists and ACTIVE currently effective prices for ACTIVE variants under ACTIVE/PUBLISHED products. Internal description and tenant/archive fields omitted; historical at and ARCHIVED/INTERNAL filters rejected.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE"],"default":"ACTIVE"}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPricePage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.read"]},"post":{"operationId":"apiClientPricingCreatePrice","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPrice"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceInput"}}}}}},"/api-client/pricing/price-lists/{listId}/prices/{id}":{"get":{"operationId":"apiClientPricingGetPrice","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.read and PUBLIC_API entitlement; tenant is derived from the verified key. API-key reads expose ACTIVE/PUBLIC lists and ACTIVE currently effective prices for ACTIVE variants under ACTIVE/PUBLISHED products. Internal description and tenant/archive fields omitted; historical at and ARCHIVED/INTERNAL filters rejected.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPrice"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.read"]},"put":{"operationId":"apiClientPricingUpdatePrice","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPrice"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceInput"}}}}}},"/api-client/pricing/price-lists/{listId}/prices/{id}/archive":{"post":{"operationId":"apiClientPricingArchivePrice","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.write and PUBLIC_API entitlement; tenant is derived from the verified key. Archived price cannot be restored or edited; frees its active validity interval. Full replacement of editable fields on PUT; omitted description resets null, visibility INTERNAL and date bounds unbounded. List code/currency and price variant/list/currency are immutable. ACTIVE price periods cannot overlap for the same tenant/list/variant; [from,to) intervals allow adjacent periods. Mutations require Idempotency-Key, current authorization, audit and atomic webhook outbox. Authorized pricing.write can manage internal/draft prices; response uses the credential-specific projection.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPrice"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyPricingInput"}}}}}},"/api-client/pricing/price-lists/{listId}/resolve/{variantId}":{"get":{"operationId":"apiClientPricingResolvePrice","tags":["Pricing"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT pricing.read and PUBLIC_API entitlement; tenant is derived from the verified key. Resolve exactly one ACTIVE price at the database statement time (optional UTC at for humans only). Missing effective price returns 404; no fallback list, discount, tax, conversion or rounding. API-key reads expose ACTIVE/PUBLIC lists and ACTIVE currently effective prices for ACTIVE variants under ACTIVE/PUBLISHED products. Internal description and tenant/archive fields omitted; historical at and ARCHIVED/INTERNAL filters rejected.","parameters":[{"name":"listId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPrice"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Overlapping active price periods, immutable identity, archived resource or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["pricing.read"]}},"/tenants/{tenantId}/inventory/warehouses":{"get":{"operationId":"tenantInventoryListWarehouses","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Cursor UUIDv7 ascending, default50/max100, unknown query rejected. Stock cursor is variantId within warehouse; others resource id.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehousePage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]},"post":{"operationId":"tenantInventoryCreateWarehouse","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Warehouse"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}":{"get":{"operationId":"tenantInventoryGetWarehouse","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Warehouse"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]},"put":{"operationId":"tenantInventoryUpdateWarehouse","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.Full replacement; only name changes, send unchanged identity fields.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Warehouse"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/archive":{"post":{"operationId":"tenantInventoryArchiveWarehouse","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Warehouse"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyInventoryInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/locations":{"get":{"operationId":"tenantInventoryListLocations","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Cursor UUIDv7 ascending, default50/max100, unknown query rejected. Stock cursor is variantId within warehouse; others resource id.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocationPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]},"post":{"operationId":"tenantInventoryCreateLocation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocationInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/locations/{id}":{"get":{"operationId":"tenantInventoryGetLocation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]},"put":{"operationId":"tenantInventoryUpdateLocation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.Full replacement; only name changes, send unchanged identity fields.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocationInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/locations/{id}/archive":{"post":{"operationId":"tenantInventoryArchiveLocation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseLocation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyInventoryInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/stock":{"get":{"operationId":"tenantInventoryListStock","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Cursor UUIDv7 ascending, default50/max100, unknown query rejected. Stock cursor is variantId within warehouse; others resource id.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryStockPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/stock/{variantId}":{"get":{"operationId":"tenantInventoryGetStock","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryStock"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/warehouses/{warehouseId}/stock/{variantId}/reconciliation":{"get":{"operationId":"tenantInventoryReconcileStock","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Read-only comparison against both immutable ledgers, using one SQL snapshot.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReconciliation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/movements":{"get":{"operationId":"tenantInventoryListMovements","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Cursor UUIDv7 ascending, default50/max100, unknown query rejected. Stock cursor is variantId within warehouse; others resource id. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"movementType","in":"query","description":"Comma-separated distinct ledger types: ADJUSTMENT_IN, ADJUSTMENT_OUT, TRANSFER, DAMAGE, LOSS, PURCHASE_RECEIPT, SALE, SUPPLIER_RETURN, INTERCOMPANY.","schema":{"type":"string","pattern":"^(ADJUSTMENT_IN|ADJUSTMENT_OUT|TRANSFER|DAMAGE|LOSS|PURCHASE_RECEIPT|SALE|SUPPLIER_RETURN|INTERCOMPANY)(,(ADJUSTMENT_IN|ADJUSTMENT_OUT|TRANSFER|DAMAGE|LOSS|PURCHASE_RECEIPT|SALE|SUPPLIER_RETURN|INTERCOMPANY))*$"}},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovementPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/movements/{id}":{"get":{"operationId":"tenantInventoryGetMovement","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovement"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/adjustments":{"post":{"operationId":"tenantInventoryCreateAdjustment","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovement"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAdjustmentInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/transfers":{"post":{"operationId":"tenantInventoryCreateTransfer","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.transfer, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovement"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryTransferInput"}}}},"x-required-permissions":["inventory.transfer"]}},"/tenants/{tenantId}/inventory/reservations":{"get":{"operationId":"tenantInventoryListReservations","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. Cursor UUIDv7 ascending, default50/max100, unknown query rejected. Stock cursor is variantId within warehouse; others resource id.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","required":false,"schema":{"enum":["ACTIVE","RELEASED","CONSUMED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservationPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]},"post":{"operationId":"tenantInventoryCreateReservation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservationInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/reservations/{id}":{"get":{"operationId":"tenantInventoryGetReservation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.read, active membership/current tenant permission. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/tenants/{tenantId}/inventory/reservations/{id}/release":{"post":{"operationId":"tenantInventoryReleaseReservation","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Requires USER inventory.adjust, active membership/current tenant permission. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.Release the entire quantity or serialized unit reservation once; unit release projects AVAILABLE with a new version. No automatic expiry or consumption.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyInventoryInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/api-client/inventory/adjustments":{"post":{"operationId":"apiClientInventoryCreateAdjustment","tags":["Inventory"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT inventory.write and PUBLIC_API, tenant derived from key. Safe availability or write receipt omits locations, reason, reference and actor; no warehouse/stock/history read endpoints for API clients. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovementReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAdjustmentInput"}}}}}},"/api-client/inventory/transfers":{"post":{"operationId":"apiClientInventoryCreateTransfer","tags":["Inventory"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT inventory.write and PUBLIC_API, tenant derived from key. Safe availability or write receipt omits locations, reason, reference and actor; no warehouse/stock/history read endpoints for API clients. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovementReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryTransferInput"}}}}}},"/api-client/inventory/reservations":{"post":{"operationId":"apiClientInventoryCreateReservation","tags":["Inventory"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT inventory.write and PUBLIC_API, tenant derived from key. Safe availability or write receipt omits locations, reason, reference and actor; no warehouse/stock/history read endpoints for API clients. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservationReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservationInput"}}}}}},"/api-client/inventory/reservations/{id}/release":{"post":{"operationId":"apiClientInventoryReleaseReservation","tags":["Inventory"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT inventory.write and PUBLIC_API, tenant derived from key. Safe availability or write receipt omits locations, reason, reference and actor; no warehouse/stock/history read endpoints for API clients. Requires Idempotency-Key, fresh authorization before replay; ledger/reservation events, stock projection, response, audit and outbox commit atomically. Quantity cannot overdraw onHand-reserved. Warehouse/location identity and archived records are immutable; warehouse archive requires zero onHand/reserved and no serialized units in custody. Quantity adjustments/transfers use nonserialized products; units have dedicated INV-2 routes. Business purchase/sale types and direct stock assignment are unavailable.Release the entire quantity or serialized unit reservation once; unit release projects AVAILABLE with a new version. No automatic expiry or consumption.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReservationReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyInventoryInput"}}}}}},"/api-client/inventory/availability/{variantId}":{"get":{"operationId":"apiClientInventoryGetAvailability","tags":["Inventory"],"security":[{"PlatformApiKey":[]}],"description":"Requires API_CLIENT inventory.read and PUBLIC_API, tenant derived from key. Safe availability or write receipt omits locations, reason, reference and actor; no warehouse/stock/history read endpoints for API clients. ","parameters":[{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAvailability"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Insufficient available stock, quantity product state, archived/immutable identity, illegal transfer, duplicate record or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.read"]}},"/tenants/{tenantId}/inventory/units":{"get":{"operationId":"tenantSerialsListUnits","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.read,inventory.serials.read. Cursor UUIDv7 default50/max100; exact indexed serial/IMEI lookup, at most one identity selector. Tenant-owned units across statuses; no FTS or substring. Machine queries reject warehouseId.  Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","required":false,"schema":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]}},{"name":"serialNumber","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"imei","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{15}$"}},{"name":"search","in":"query","required":false,"description":"A piece of an IMEI or of a serial number: units with an identifier that contains it. Not combined with serialNumber or imei.","schema":{"type":"string","maxLength":100,"pattern":"^[A-Za-z0-9._:/-]+$"}},{"name":"warehouseId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read","inventory.serials.read"]},"post":{"operationId":"tenantSerialsCreateUnit","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.adjust. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/units/{id}":{"get":{"operationId":"tenantSerialsGetUnit","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.read,inventory.serials.read. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnit"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read","inventory.serials.read"]}},"/tenants/{tenantId}/inventory/units/{id}/movements":{"post":{"operationId":"tenantSerialsMoveUnit","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership; operation transaction requires inventory.transfer for TRANSFER, inventory.adjust for all other enabled moves. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitMovementInput"}}}},"x-required-permissions":[]},"get":{"operationId":"tenantSerialsListUnitMovements","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.read,inventory.serials.read. Physical movements only, quantity 1; reservation records/releases are separate. Unit versions include both streams; reconciliation compares complete source. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryMovementPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read","inventory.serials.read"]}},"/tenants/{tenantId}/inventory/units/{id}/reservations":{"post":{"operationId":"tenantSerialsReserveUnit","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.adjust. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReservationReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReservationInput"}}}},"x-required-permissions":["inventory.adjust"]}},"/tenants/{tenantId}/inventory/units/{id}/reconciliation":{"get":{"operationId":"tenantSerialsReconcileUnit","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.read,inventory.serials.read. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReconciliation"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read","inventory.serials.read"]}},"/tenants/{tenantId}/inventory/warehouses/{id}/unit-summary/{variantId}":{"get":{"operationId":"tenantSerialsGetUnitSummary","tags":["Inventory units"],"security":[{"SupabaseBearer":[]}],"description":"USER with active membership and current permissions inventory.read. Bounded per-variant warehouse counts by status, at most nine items; no unit IDs or identifiers. ","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitSummary"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["inventory.read"]}},"/api-client/inventory/units":{"get":{"operationId":"apiClientSerialsListUnits","tags":["Inventory units"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT, PUBLIC_API and scopes inventory.read,inventory.serials.read. Dedicated identity reads omit internal location/actor/cost. Cursor UUIDv7 default50/max100; exact indexed serial/IMEI lookup, at most one identity selector. Tenant-owned units across statuses; no FTS or substring. Machine queries reject warehouseId. ","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"variantId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","required":false,"schema":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]}},{"name":"serialNumber","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"imei","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{15}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiInventoryUnitPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.read","inventory.serials.read"]},"post":{"operationId":"apiClientSerialsCreateUnit","tags":["Inventory units"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT, PUBLIC_API and scopes inventory.write. Dedicated identity reads omit internal location/actor/cost. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitInput"}}}}}},"/api-client/inventory/units/{id}":{"get":{"operationId":"apiClientSerialsGetUnit","tags":["Inventory units"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT, PUBLIC_API and scopes inventory.read,inventory.serials.read. Dedicated identity reads omit internal location/actor/cost. ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiInventoryUnit"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.read","inventory.serials.read"]}},"/api-client/inventory/units/{id}/movements":{"post":{"operationId":"apiClientSerialsMoveUnit","tags":["Inventory units"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT, PUBLIC_API and scopes inventory.write. Dedicated identity reads omit internal location/actor/cost. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitMovementInput"}}}}}},"/api-client/inventory/units/{id}/reservations":{"post":{"operationId":"apiClientSerialsReserveUnit","tags":["Inventory units"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT, PUBLIC_API and scopes inventory.write. Dedicated identity reads omit internal location/actor/cost. Requires Idempotency-Key and fresh authorization before replay. Unit projection, physical/reservation ledger, audit, receipt and inventory.updated outbox/fanout/queue commit atomically. Write receipt never discloses serial/IMEI; conflicts and stale versions return 409. ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4 or UUIDv7. Normalized input fingerprint; same actor/tenant/operation and key replay for 24 hours. Changed input conflicts; authorization rechecked before replay."}],"responses":{"201":{"description":"Success","headers":{"X-Request-Id":{"schema":{"type":"string","format":"uuid"}},"X-RateLimit-Limit":{"description":"Effective requests per fixed minute window","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining capacity of the most restrictive dimension","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Redis window reset, Unix seconds","schema":{"type":"integer"}},"Idempotency-Replayed":{"schema":{"enum":["true"]},"description":"Present on successful replay."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReservationReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryUnitReservationInput"}}}}}},"/tenants/{tenantId}/search":{"get":{"operationId":"tenantUniversalSearch","tags":["Universal Search"],"security":[{"SupabaseBearer":[]}],"description":"USER catalog.read, active membership and current permissions. Active products/variants by default, includeArchived=true admits archived catalog records. Draft products are ERP-visible. Exact pipeline precedence: IMEI, SKU, barcode, serial, model. Prefix FTS and word trigram are fallback only when there are no authorized visible exact matches. IMEI/SKU/serial are exact/indexed and never enter automatic text projection. Unit branches participate only with BOTH inventory.read and inventory.serials.read checked freshly inside transaction; lacking either quietly skips unit lookup. Unit hits expose IDs/status/version/condition/grade with safe catalog fields, no IMEI/serial, custody, actor, arbitrary attributes, costs, prices or audit. Text indexes name/active brand/model/storage/color/condition/grade/SIM and curated aliases using simple tsvector, unaccent and pg_trgm; aliases managed by Catalog write. Literal input, no user tsquery syntax. Stage ascending/rank descending/kind/id tie break, dedup per kind/id. No total counts or side-effect writes; query/cursor are never logged. Fresh filters enforced after projection. No anonymous access, external search service or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200},"description":"NFKC/trim/collapse spaces, max12 alphanumeric tokens; no controls. Exact input may be one character; text prefixes ignore tokens shorter than two; fuzzy requires at least three alphanumeric characters."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":600,"pattern":"^[A-Za-z0-9_-]+$"}},{"name":"includeArchived","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Human ERP only; true rejected for API clients."}],"responses":{"200":{"description":"Ranked search page; exact hits first, each resource once. Empty results return items=[] and nextCursor=null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["catalog.read"],"x-optional-serial-permissions":["inventory.read","inventory.serials.read"]}},"/api-client/search":{"get":{"operationId":"apiClientUniversalSearch","tags":["Universal Search"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT catalog.read + PUBLIC_API, tenant derived from key. Only active variants of active published products, including optional exact unit hits. includeArchived=true rejected. Exact pipeline precedence: IMEI, SKU, barcode, serial, model. Prefix FTS and word trigram are fallback only when there are no authorized visible exact matches. IMEI/SKU/serial are exact/indexed and never enter automatic text projection. Unit branches participate only with BOTH inventory.read and inventory.serials.read checked freshly inside transaction; lacking either quietly skips unit lookup. Unit hits expose IDs/status/version/condition/grade with safe catalog fields, no IMEI/serial, custody, actor, arbitrary attributes, costs, prices or audit. Text indexes name/active brand/model/storage/color/condition/grade/SIM and curated aliases using simple tsvector, unaccent and pg_trgm; aliases managed by Catalog write. Literal input, no user tsquery syntax. Stage ascending/rank descending/kind/id tie break, dedup per kind/id. No total counts or side-effect writes; query/cursor are never logged. Fresh filters enforced after projection. No anonymous access, external search service or business UI.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200},"description":"NFKC/trim/collapse spaces, max12 alphanumeric tokens; no controls. Exact input may be one character; text prefixes ignore tokens shorter than two; fuzzy requires at least three alphanumeric characters."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":600,"pattern":"^[A-Za-z0-9_-]+$"}},{"name":"includeArchived","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Human ERP only; true rejected for API clients."}],"responses":{"200":{"description":"Ranked search page; exact hits first, each resource once. Empty results return items=[] and nextCursor=null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["catalog.read"],"x-optional-serial-scopes":["inventory.read","inventory.serials.read"]}},"/tenants/{tenantId}/purchases/suppliers":{"get":{"operationId":"tenantListSuppliers","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"post":{"operationId":"tenantCreateSupplier","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierInput"}}}}}},"/tenants/{tenantId}/purchases/suppliers/{id}":{"get":{"operationId":"tenantGetSupplier","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Supplier"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"put":{"operationId":"tenantUpdateSupplier","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierInput"}}}}}},"/tenants/{tenantId}/purchases/suppliers/{id}/archive":{"post":{"operationId":"tenantArchiveSupplier","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCommand"}}}}}},"/tenants/{tenantId}/purchases/orders":{"get":{"operationId":"tenantListOrders","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]}},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderHeaderPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"post":{"operationId":"tenantCreateOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderInput"}}}}}},"/tenants/{tenantId}/purchases/orders/{id}":{"get":{"operationId":"tenantGetOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrder"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"put":{"operationId":"tenantUpdateOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderUpdate"}}}}}},"/tenants/{tenantId}/purchases/orders/{id}/approve":{"post":{"operationId":"tenantApproveOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.approve"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseVersionInput"}}}}}},"/tenants/{tenantId}/purchases/orders/{id}/cancel":{"post":{"operationId":"tenantCancelOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.approve"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseVersionInput"}}}}}},"/tenants/{tenantId}/purchases/orders/{id}/receipts":{"get":{"operationId":"tenantListReceipts","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptWritePage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"post":{"operationId":"tenantReceiveOrder","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptWrite"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create","inventory.adjust"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptInput"}}}}}},"/tenants/{tenantId}/purchases/receipts/{id}":{"get":{"operationId":"tenantGetReceipt","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]}},"/tenants/{tenantId}/purchases/incoming":{"get":{"operationId":"tenantPurchaseIncoming","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"USER requires active membership and fresh permissions. Supplier management uses purchases.read/create; approval/cancellation requires purchases.approve. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseIncomingPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]}},"/api-client/purchases/suppliers":{"get":{"operationId":"apiClientListSuppliers","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.read"]},"post":{"operationId":"apiClientCreateSupplier","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierInput"}}}}}},"/api-client/purchases/suppliers/{id}":{"get":{"operationId":"apiClientGetSupplier","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Supplier"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.read"]},"put":{"operationId":"apiClientUpdateSupplier","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierInput"}}}}}},"/api-client/purchases/suppliers/{id}/archive":{"post":{"operationId":"apiClientArchiveSupplier","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCommand"}}}}}},"/api-client/purchases/orders":{"get":{"operationId":"apiClientListOrders","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPurchaseOrderHeaderPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]},"post":{"operationId":"apiClientCreateOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderInput"}}}}}},"/api-client/purchases/orders/{id}":{"get":{"operationId":"apiClientGetOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPurchaseOrder"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]},"put":{"operationId":"apiClientUpdateOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderUpdate"}}}}}},"/api-client/purchases/orders/{id}/approve":{"post":{"operationId":"apiClientApproveOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseVersionInput"}}}}}},"/api-client/purchases/orders/{id}/cancel":{"post":{"operationId":"apiClientCancelOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseVersionInput"}}}}}},"/api-client/purchases/orders/{id}/receipts":{"get":{"operationId":"apiClientListReceipts","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptWritePage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]},"post":{"operationId":"apiClientReceiveOrder","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptWrite"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write","inventory.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptInput"}}}}}},"/api-client/purchases/receipts/{id}":{"get":{"operationId":"apiClientGetReceipt","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiGoodsReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]}},"/api-client/purchases/incoming":{"get":{"operationId":"apiClientPurchaseIncoming","tags":["Procurement"],"security":[{"PlatformApiKey":[]}],"description":"API_CLIENT requires explicit scopes and PUBLIC_API; tenant from key. Internal procurement drafts and costs are available only through purchase scopes; custody/actor/tenant metadata omitted. Drafts can be fully replaced with expectedVersion; approval fixes the snapshot. Receipts require purchase creation/write AND Inventory adjustment/write. They atomically append PURCHASE_RECEIPT movements/new serial units, preserve exact costs, update received/pending projections, audit, replay and outbox. No excess receipt, reused serial identity, direct stock edits, unit identifiers in receipt DTOs, valuation, FX, tax, invoice or payment. Services/untracked lines use administrative acceptance without inventory effects. Cancel an open order to stop outstanding incoming; previously posted receipts remain. Lists use UUIDv7 cursor50/max100; incoming is outstanding per open approved order line, excludes drafts/cancelled. Decimals are strings: costs/quantities scale6, quantity*cost totals scale12 without rounding. Up to100 distinct lines and100 units total per receipt. Order number+LegalEntity are immutable; supplier code remains reserved. No anonymous access or business UI.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPurchaseIncomingPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]}},"/tenants/{tenantId}/sales/customers":{"get":{"operationId":"tenantSalesGetCustomers","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"post":{"operationId":"tenantSalesPostCustomers","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerInput"}}}}}},"/tenants/{tenantId}/sales/customers/{id}":{"get":{"operationId":"tenantSalesGetCustomers_id","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"put":{"operationId":"tenantSalesPutCustomers_id","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerInput"}}}}}},"/tenants/{tenantId}/sales/customers/{id}/archive":{"post":{"operationId":"tenantSalesPostCustomers_id_archive","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCommand"}}}}}},"/tenants/{tenantId}/sales/orders":{"get":{"operationId":"tenantSalesGetOrders","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]}},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderHeaderPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"post":{"operationId":"tenantSalesPostOrders","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderInput"}}}}}},"/tenants/{tenantId}/sales/orders/{id}":{"get":{"operationId":"tenantSalesGetOrders_id","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrder"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.read"]},"put":{"operationId":"tenantSalesPutOrders_id","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.create"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderUpdate"}}}}}},"/tenants/{tenantId}/sales/orders/{id}/confirm":{"post":{"operationId":"tenantSalesPostOrders_id_confirm","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.approve"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesConfirmInput"}}}}}},"/tenants/{tenantId}/sales/orders/{id}/cancel":{"post":{"operationId":"tenantSalesPostOrders_id_cancel","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.approve"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesVersionInput"}}}}}},"/tenants/{tenantId}/sales/orders/{id}/complete":{"post":{"operationId":"tenantSalesPostOrders_id_complete","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-permissions":["purchases.approve"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesVersionInput"}}}}}},"/api-client/sales/customers":{"get":{"operationId":"apiSalesGetCustomers","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"],"default":"ACTIVE"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.read"]},"post":{"operationId":"apiSalesPostCustomers","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerInput"}}}}}},"/api-client/sales/customers/{id}":{"get":{"operationId":"apiSalesGetCustomers_id","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.read"]},"put":{"operationId":"apiSalesPutCustomers_id","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerInput"}}}}}},"/api-client/sales/customers/{id}/archive":{"post":{"operationId":"apiSalesPostCustomers_id_archive","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["suppliers.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyCommand"}}}}}},"/api-client/sales/orders":{"get":{"operationId":"apiSalesGetOrders","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSalesOrderHeaderPage"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]},"post":{"operationId":"apiSalesPostOrders","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"201":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderInput"}}}}}},"/api-client/sales/orders/{id}":{"get":{"operationId":"apiSalesGetOrders_id","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSalesOrder"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.read"]},"put":{"operationId":"apiSalesPutOrders_id","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderUpdate"}}}}}},"/api-client/sales/orders/{id}/confirm":{"post":{"operationId":"apiSalesPostOrders_id_confirm","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesConfirmInput"}}}}}},"/api-client/sales/orders/{id}/cancel":{"post":{"operationId":"apiSalesPostOrders_id_cancel","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesVersionInput"}}}}}},"/api-client/sales/orders/{id}/complete":{"post":{"operationId":"apiSalesPostOrders_id_complete","tags":["Sales"],"security":[{"PlatformApiKey":[]}],"description":"Tenant-scoped sales with fresh USER RBAC or API_CLIENT scopes and PUBLIC_API entitlement. Customers require customers.read/write. Orders require sales.read; draft writes require sales.create (machine sales.write) plus pricing.read. Confirmation adds inventory.adjust (machine inventory.write), refreshes current prices, freezes snapshots and reserves all stock/selected unit UUIDs. Completion requires sales.create+inventory.adjust (machine sales.write+inventory.write) and atomically consumes reservations and appends SALE movements; serialized units become SOLD without custody. Cancellation requires sales.cancel+inventory.adjust (machine sales.write+inventory.write) and releases reservations without reversing physical movements. State DRAFT→CONFIRMED→COMPLETED or cancellation before completion; expectedVersion mandatory. Single legal entity, warehouse and price-list currency per order; at most100 distinct lines and100 serial units. Decimal quantities/prices scale6, unrounded commercial totals scale12. All writes require Idempotency-Key; replay is denied after permission/scope/entitlement revocation. Machine pricing accepts public lists and published active variants. No anonymous access, purchase costs/margins, serial identities, payment, tax, invoice, return or UI in the Sales endpoints; cash checkout composes delivery through POS.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7; replay24h under fresh authorization, input fingerprint bound to aggregate ID."}],"responses":{"200":{"description":"Success","headers":{"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderReceipt"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid access token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Identity, membership or permission denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate permanent identity/IMEI, stale unit version, reserved/illegal unit state, custody/legal entity constraint or idempotency conflict.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Payload too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Per-minute rate or monthly quota exceeded; authenticated API clients require PUBLIC_API entitlement.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}},"headers":{"Retry-After":{"description":"Seconds before retrying; quota reset is UTC next month.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal failure","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Auth/database/governance unavailable; no memory fallback for Redis.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"x-required-scopes":["purchases.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesVersionInput"}}}}}},"/tenants/{tenantId}/pos/registers":{"get":{"operationId":"tenantPosGetRegisters","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["ACTIVE","ARCHIVED"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegisterPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPosPostRegisters","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions settings.manage. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegister"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegisterInput"}}}}}},"/tenants/{tenantId}/pos/registers/{id}":{"get":{"operationId":"tenantPosGetRegistersById","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegister"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/pos/registers/{id}/archive":{"post":{"operationId":"tenantPosPostRegistersByIdArchive","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions settings.manage. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegister"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosEmpty"}}}}}},"/tenants/{tenantId}/pos/sessions":{"get":{"operationId":"tenantPosGetSessions","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["OPEN","CLOSED"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSessionPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPosPostSessions","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSession"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosOpenInput"}}}}}},"/tenants/{tenantId}/pos/sessions/{id}":{"get":{"operationId":"tenantPosGetSessionsById","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSession"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/pos/sessions/{id}/close":{"post":{"operationId":"tenantPosPostSessionsByIdClose","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSession"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosCloseInput"}}}}}},"/tenants/{tenantId}/pos/sessions/{id}/checkout":{"post":{"operationId":"tenantPosPostSessionsByIdCheckout","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create, pricing.read, inventory.adjust. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosCheckoutInput"}}}}}},"/tenants/{tenantId}/pos/receipts":{"get":{"operationId":"tenantPosGetReceipts","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"sessionId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosReceiptPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/pos/receipts/{id}":{"get":{"operationId":"tenantPosGetReceiptsById","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. One open operator-bound session per register. Configuration immutable except archive without an open session. Checkout accepts only a confirmed Sales order matching entity/warehouse/list/currency, checks both versions and cash precision, and atomically delivers Sales, consumes Inventory reservations, inserts one immutable receipt with its payment components and increments the session version. The sale is collected in full with cash, transfer, debit or credit card, cheque or other methods, alone or mixed; components add up to the total exactly, change is given only in cash and is exact, and collections made on an external terminal or bank are recorded: no acquirer is contacted and no card number or security code is accepted. No partial delivery, credit sale, fiscal invoice, taxes, discount, rounding, FX or refunds. Cash entering or leaving the till outside a sale is a cash movement. Closing records expected cash (opening amount, cash portions of sales and cash movements; never cards or transfers), counted cash and signed variance; no reopening. All writes are idempotent and all reads/writes tenant scoped. Events expose IDs only.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family, permissions or session operator","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash, precision, inventory or duplicate receipt conflict","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/workspace":{"get":{"operationId":"getHumanWorkspace","summary":"Authorized workspace, legal entities and branches","security":[{"SupabaseBearer":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Authorized workspace metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workspace"}}}},"401":{"description":"Authentication required"},"403":{"description":"Active membership required"}}}},"/platform/tenants":{"get":{"operationId":"listPlatformCompanies","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[{"in":"query","name":"q","schema":{"type":"string","maxLength":100}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"in":"query","name":"cursor","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformCompanies"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/catalog/variant-references":{"get":{"operationId":"catalogVariantReferences","summary":"Resolve authorized variant labels by up to 100 UUIDv7 IDs or 100 SKUs","security":[{"SupabaseBearer":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"ids","in":"query","required":false,"schema":{"type":"string","maxLength":3699},"description":"Comma-separated distinct UUIDv7 variant IDs. Unknown or foreign variants are omitted. Requires catalog.read. Exactly one of `ids` and `skus` is sent."},{"name":"skus","in":"query","required":false,"schema":{"type":"string","maxLength":10099},"description":"Comma-separated distinct SKUs, normalised as the catalogue stores them. Returns the variants that hold them, archived ones included: a SKU stays taken after its variant is archived. Unknown SKUs are omitted, so what is missing from the answer is free. Exactly one of `ids` and `skus` is sent."}],"responses":{"200":{"description":"Authorized workspace metadata","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogVariantReference"}}}}}}},"401":{"description":"Authentication required"},"403":{"description":"Active membership required"}}}},"/tenants/{tenantId}/sales/quotations":{"get":{"operationId":"tenantSalesGetQuotations","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","ISSUED","ACCEPTED","REJECTED","CANCELLED"]}},{"name":"customerId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"salesOrderId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantSalesPostQuotations","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create, pricing.read. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/quotations/{id}":{"get":{"operationId":"tenantSalesGetQuotationsById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quotation"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantSalesPutQuotationsById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create, pricing.read. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/quotations/{id}/issue":{"post":{"operationId":"tenantSalesPostQuotationsByIdIssue","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create, pricing.read. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/quotations/{id}/accept":{"post":{"operationId":"tenantSalesPostQuotationsByIdAccept","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create; pricing.read as well when it originates a sales order. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationAcceptInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/quotations/{id}/reject":{"post":{"operationId":"tenantSalesPostQuotationsByIdReject","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/quotations/{id}/cancel":{"post":{"operationId":"tenantSalesPostQuotationsByIdCancel","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. A quotation is a proposal with an exact list-price snapshot: it never reserves, deducts or delivers stock. DRAFT is editable and re-priced on every save; ISSUED is frozen; ACCEPTED, REJECTED and CANCELLED are final. Issuing requires every snapshot to equal the current list price. Accepting is refused after validUntil and may originate one draft sales order with the quoted lines, only while list prices still equal the quoted prices; reserving, collecting and delivering stay explicit sales order and POS actions. No discounts, taxes, negotiated prices, fiscal documents or sending. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, expiry, price snapshot, duplicate number or archived party","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/reservations":{"get":{"operationId":"tenantSalesGetReservations","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read, inventory.read, customers.read. Read-only view of Inventory reservations created by confirmed sales orders, with the order and customer they belong to. Inventory remains the only source of reserved stock; nothing is duplicated.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["ACTIVE","RELEASED","CONSUMED"],"default":"ACTIVE"}},{"name":"customerId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommercialReservationPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders":{"get":{"operationId":"tenantInventoryGetTransferOrders","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]}},{"name":"warehouseId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Origin, destination or transit warehouse."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantInventoryPostTransferOrders","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders/{id}":{"get":{"operationId":"tenantInventoryGetTransferOrdersById","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrder"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantInventoryPutTransferOrdersById","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders/{id}/approve":{"post":{"operationId":"tenantInventoryPostTransferOrdersByIdApprove","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer, inventory.adjust. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders/{id}/cancel":{"post":{"operationId":"tenantInventoryPostTransferOrdersByIdCancel","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders/{id}/dispatch":{"post":{"operationId":"tenantInventoryPostTransferOrdersByIdDispatch","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDispatchInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/transfer-orders/{id}/receipts":{"post":{"operationId":"tenantInventoryPostTransferOrdersByIdReceipts","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer; inventory.adjust as well when a line is LOST. Transfer orders move goods between two warehouses of one legal entity through an IN_TRANSIT warehouse of that entity. Approval moves nothing. Dispatch ships the whole order from the origin into transit using the inventory ledger, so goods are never available in two places; serialized lines name the exact units and every unit keeps its identity. Receipts resolve goods in transit as RECEIVED at the destination, LOST, or RETURNED to the origin; unresolved goods stay in transit and the order stays PARTIALLY_RECEIVED. Cancellation is possible only before dispatch and never restores stock. Goods held in transit by an order cannot leave through manual movements. No partial dispatch, costs, valuation or transfers across legal entities. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferReceiptInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices":{"get":{"operationId":"tenantSalesGetInvoices","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","ISSUED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"orderId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Sales order (sales) or purchase order (purchases)."},{"name":"open","in":"query","schema":{"enum":["true"]},"description":"Issued invoices with a balance."},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"number","in":"query","required":false,"schema":{"type":"string","maxLength":64}},{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"totalMin","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]+(\\.[0-9]{1,6})?$"}},{"name":"totalMax","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]+(\\.[0-9]{1,6})?$"}},{"name":"warehouseId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantSalesPostInvoices","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}":{"get":{"operationId":"tenantSalesGetInvoicesById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantSalesPutInvoicesById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}/issue":{"post":{"operationId":"tenantSalesPostInvoicesByIdIssue","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}/void":{"post":{"operationId":"tenantSalesPostInvoicesByIdVoid","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}/pos-receipt":{"post":{"operationId":"tenantSalesPostInvoicesByIdPosReceipt","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/payments":{"get":{"operationId":"tenantSalesGetPayments","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["PENDING","RECORDED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantSalesPostPayments","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/payments/{id}":{"get":{"operationId":"tenantSalesGetPaymentsById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/payments/{id}/apply":{"post":{"operationId":"tenantSalesPostPaymentsByIdApply","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/payments/{id}/confirm":{"post":{"operationId":"tenantSalesPostPaymentsByIdConfirm","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/payments/{id}/void":{"post":{"operationId":"tenantSalesPostPaymentsByIdVoid","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}/recognize-revenue":{"post":{"operationId":"tenantSalesPostInvoicesByIdRecognizeRevenue","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read, accounting.post. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRecognition"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes":{"get":{"operationId":"tenantSalesGetCreditNotes","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["REQUESTED","RECOGNIZED","REJECTED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantSalesPostCreditNotes","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}":{"get":{"operationId":"tenantSalesGetCreditNotesById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credit"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantSalesPutCreditNotesById","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}/recognize":{"post":{"operationId":"tenantSalesPostCreditNotesByIdRecognize","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditRecognitionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}/reject":{"post":{"operationId":"tenantSalesPostCreditNotesByIdReject","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}/void":{"post":{"operationId":"tenantSalesPostCreditNotesByIdVoid","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}/apply":{"post":{"operationId":"tenantSalesPostCreditNotesByIdApply","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/credit-notes/{id}/refunds":{"post":{"operationId":"tenantSalesPostCreditNotesByIdRefunds","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.cancel. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditRefundInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills":{"get":{"operationId":"tenantPurchasesGetBills","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion. Human workspace filters are combined with AND, applied before cursor pagination and tenant/warehouse access controls. Text matching is literal case-insensitive containment. productId includes all variants of the product, including archived variants; document filters never duplicate documents. Date and total bounds are inclusive.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","ISSUED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"orderId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Sales order (sales) or purchase order (purchases)."},{"name":"open","in":"query","schema":{"enum":["true"]},"description":"Issued invoices with a balance."},{"name":"productId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"number","in":"query","required":false,"schema":{"type":"string","maxLength":64}},{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"totalMin","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]+(\\.[0-9]{1,6})?$"}},{"name":"totalMax","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]+(\\.[0-9]{1,6})?$"}},{"name":"warehouseId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPurchasesPostBills","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}":{"get":{"operationId":"tenantPurchasesGetBillsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantPurchasesPutBillsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/issue":{"post":{"operationId":"tenantPurchasesPostBillsByIdIssue","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/void":{"post":{"operationId":"tenantPurchasesPostBillsByIdVoid","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/payments":{"get":{"operationId":"tenantPurchasesGetPayments","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["PENDING","RECORDED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPurchasesPostPayments","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/payments/{id}":{"get":{"operationId":"tenantPurchasesGetPaymentsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/payments/{id}/apply":{"post":{"operationId":"tenantPurchasesPostPaymentsByIdApply","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/payments/{id}/confirm":{"post":{"operationId":"tenantPurchasesPostPaymentsByIdConfirm","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/payments/{id}/void":{"post":{"operationId":"tenantPurchasesPostPaymentsByIdVoid","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/recognize-expense":{"post":{"operationId":"tenantPurchasesPostBillsByIdRecognizeExpense","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read, accounting.post. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseRecognitionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRecognition"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits":{"get":{"operationId":"tenantPurchasesGetCredits","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["REQUESTED","RECOGNIZED","REJECTED","VOID"]}},{"name":"partyId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPurchasesPostCredits","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}":{"get":{"operationId":"tenantPurchasesGetCreditsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credit"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantPurchasesPutCreditsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}/recognize":{"post":{"operationId":"tenantPurchasesPostCreditsByIdRecognize","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditRecognitionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}/reject":{"post":{"operationId":"tenantPurchasesPostCreditsByIdReject","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}/void":{"post":{"operationId":"tenantPurchasesPostCreditsByIdVoid","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}/apply":{"post":{"operationId":"tenantPurchasesPostCreditsByIdApply","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/credits/{id}/refunds":{"post":{"operationId":"tenantPurchasesPostCreditsByIdRefunds","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Commercial documents, not fiscal ones: no tax, fiscal numbering, electronic issuance, rounding or currency conversion. An invoice is DRAFT (editable), ISSUED (frozen) or VOID (only when nothing was applied). Its total is the exact sum of its lines and must fit 6 decimals. Balances are never stored: an invoice balance is its total minus applications; a payment has an unapplied remainder; a credit is REQUESTED until a real document recognises it, and only a RECOGNIZED credit has an available balance, reduced by applications and refunds. Applications are immutable and join documents of the same party, legal entity, currency and side; they never exceed either balance. A payment states its method (cash, transfer, card, cheque, other), for a card whether debit or credit, and may name the money account it lands in or leaves from; a PENDING payment is money announced and not confirmed: it carries no applications and settles nothing until it is confirmed. Card numbers and security codes are never accepted. A sales order collected at the register is settled only by that receipt, recorded once as one payment per payment component, so the collection is never counted twice and linking never brings money in again; the POS records are not changed. Credits and physical returns are independent: neither creates the other, and naming a variant or unit moves no inventory. Saving or issuing an invoice moves none either: the devices typed on a bill and the units chosen on a sales invoice are only what its lines carry, until the invoice is confirmed together with its receipt or its delivery (see those operations). A draft may be incomplete. An invoice is posted (issued, confirmed or recognised) only with every unit of every line of a serialized article identified and linked to it, exactly as many as the line bills, and it is never completed afterwards. How an article is tracked is read from its product, whatever the request says; a line that names a physical unit without its SKU is a line of a serialized article too (409 FULFILMENT_INCOMPLETE). Issuing alone therefore works for a bill whose purchase order already received the units its lines name, and for a sales invoice whose order reserved or delivered them, the sales of the register included: the invoice keeps those units from the instant it is issued, and nothing enters or leaves again. An invoice with no order behind it that bills a serialized article is not issued alone, whatever it carries and with or without a price list (409 FULFILMENT_REQUIRED): it is confirmed together with its receipt or its delivery. A line short of units is refused with 409 UNIT_COUNT_MISMATCH. Each place in `errors` says how many units the line bills (`required`) and how many are identified (`identified`): counts, never an identifier. Recognising revenue or expense by decision is refused the same way for an invoice that bills a serialized article. Quantity articles and services need no units and behave as before. A credit is financial unless a supplier credit states COST_CORRECTION and names the receipt lines it corrects: only then does recognising it change what those goods are worth, where they still are, and never by more than they cost. A stated money account is validated against the active accounts of the entity that fit the method (PAYMENT_ACCOUNT_INVALID). Cash refunded to a customer from the cash account of the tills names the open session it leaves (CASH_SESSION_REQUIRED): the refund lowers the expected cash of that session and posts one entry; cash from anywhere else names another cash account and touches no session. When the legal entity keeps books, issuing, paying, applying, recognising and refunding each post their entry in the same transaction or fail with ACCOUNTING_SETUP_REQUIRED, ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED or ACCOUNTING_AMOUNT_PRECISION; voiding posts the mirror entry. An invoice never recognises revenue by itself: revenue is earned on delivery of its order, or by an explicit recognition when it has no order. Writes are idempotent and tenant scoped; state changes carry expectedVersion.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditRefundInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient balance, mismatched party/entity/currency, duplicate number, register receipt rule, or a specific block: PAYMENT_ACCOUNT_INVALID, CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/returns":{"get":{"operationId":"tenantPurchasesGetReturns","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","AUTHORIZED","SHIPPED","CANCELLED"]}},{"name":"supplierId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPurchasesPostReturns","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/returns/{id}":{"get":{"operationId":"tenantPurchasesGetReturnsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturn"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantPurchasesPutReturnsById","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/returns/{id}/authorize":{"post":{"operationId":"tenantPurchasesPostReturnsByIdAuthorize","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/returns/{id}/cancel":{"post":{"operationId":"tenantPurchasesPostReturnsByIdCancel","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/returns/{id}/ship":{"post":{"operationId":"tenantPurchasesPostReturnsByIdShip","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create, inventory.adjust. Physical return of goods to a supplier from one warehouse. DRAFT is editable, AUTHORIZED is frozen, SHIPPED is final; cancelling is possible only before shipping. Authorising moves nothing. Shipping sends the whole return once through the inventory ledger as SUPPLIER_RETURN; serialized lines name the exact units, which leave custody as RETURNED and keep their identity. A return never creates, recognises or applies a credit. No costs, valuation or carrier data. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnShipInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierReturnReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in the warehouse or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders":{"get":{"operationId":"tenantInventoryGetImportOrders","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]}},{"name":"legalEntityId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Origin or destination legal entity."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOrderPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantInventoryPostImportOrders","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOrderInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders/{id}":{"get":{"operationId":"tenantInventoryGetImportOrdersById","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOrder"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantInventoryPutImportOrdersById","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOrderUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders/{id}/approve":{"post":{"operationId":"tenantInventoryPostImportOrdersByIdApprove","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer, inventory.adjust. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders/{id}/cancel":{"post":{"operationId":"tenantInventoryPostImportOrdersByIdCancel","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders/{id}/dispatch":{"post":{"operationId":"tenantInventoryPostImportOrdersByIdDispatch","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportDispatchInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/import-orders/{id}/receipts":{"post":{"operationId":"tenantInventoryPostImportOrdersByIdReceipts","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.transfer; inventory.adjust as well when a line is LOST. Import orders move goods between two legal entities of the same tenant; the existing transfer still refuses to cross entities. The order states who owns the goods in transit: the transit warehouse belongs to that entity. Exactly one ledger movement (INTERCOMPANY) crosses entities, at receipt when the origin owns the transit and at dispatch when the destination does; a return to the origin crosses back in the second case. Approval moves nothing; dispatch ships the whole order; receipts resolve goods as RECEIVED, LOST or RETURNED and the rest stays in transit; cancellation is possible only before dispatch. Serialized units keep their identifier, serial and IMEI and change legal entity with that single movement: they are never registered again. Declared values and the export/import document references are statements kept on the order; no costs, customs duties, taxes, FX or commercial invoices between entities are created. Writes are idempotent, versioned and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportReceiptInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, insufficient stock, unit not in transit, warehouse entity/type or duplicate number","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/reports/stock":{"get":{"operationId":"tenantReportsGetStock","tags":["Reports"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read, catalog.read. Read-only report computed from the ledgers and documents of the tenant at request time; nothing is stored, estimated or rounded. `legalEntityId` narrows it to one legal entity.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"legalEntityId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"warehouseId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"productId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Only the variants of this product, in every warehouse that holds them."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockReportPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/reports/in-transit":{"get":{"operationId":"tenantReportsGetInTransit","tags":["Reports"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read, catalog.read. Read-only report computed from the ledgers and documents of the tenant at request time; nothing is stored, estimated or rounded. `legalEntityId` narrows it to one legal entity.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Owner, origin or destination legal entity."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransitReportPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/reports/receivables":{"get":{"operationId":"tenantReportsGetReceivables","tags":["Reports"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read, customers.read. Read-only report computed from the ledgers and documents of the tenant at request time; nothing is stored, estimated or rounded. `legalEntityId` narrows it to one legal entity.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceReportPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/reports/payables":{"get":{"operationId":"tenantReportsGetPayables","tags":["Reports"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. Read-only report computed from the ledgers and documents of the tenant at request time; nothing is stored, estimated or rounded. `legalEntityId` narrows it to one legal entity.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceReportPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/payment-options":{"get":{"operationId":"tenantAccountingGetPaymentOptions","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions payments.accounts.read, an operational duty of whoever collects or pays. It lists the active money accounts of one entity that fit each method, the one preselected and what a till movement may be booked against. It carries no balance, mapping, entry or configuration, and accounting.read is not needed. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"An entity without books answers enabled=false and no account."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentOptions"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/default":{"get":{"operationId":"tenantValuationGetDefault","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationDefault"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantValuationPutDefault","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure and settings.manage. Sets the company default: what a legal entity inherits when its books open without stating a method. It is a new version; ledgers that exist keep their method, their valued stock and their entries. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationDefaultInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationDefault"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/cost-adjustments":{"get":{"operationId":"tenantValuationGetCostAdjustments","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. A purchase cost corrected after the goods were received, by a supplier credit whose reason is COST_CORRECTION or by matching a supplier bill with its receipt lines. No other credit ever touches inventory. Each correction names receipt lines; for each one the valued history says where those goods are now: what the entity still holds changes value where it is, in stock or in transit, and what already left (sold, lost, returned, sent to another entity) goes to the PURCHASE_COST_VARIANCE account. Under FIFO the layers of the receipt decide what is still held, which need not be the same physical units or IMEI; under weighted average every exit took its proportion of the pool. Nothing is recalculated backwards and no posted entry is rewritten: an adjustment is a new dated event with one ledger entry, and it is undone by another adjustment that names it. A receipt line is matched with one bill line at a time, a credit adjusts once, and a correction never leaves goods with a negative cost. Receipts older than the ledger have no cost in it: 409 COST_SOURCE_NOT_VALUED.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"sourceId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Supplier credit or supplier bill behind the adjustments."},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostAdjustmentPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/orders/{id}/received-lines":{"get":{"operationId":"tenantPurchasesGetOrdersByIdReceivedLines","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. A purchase cost corrected after the goods were received, by a supplier credit whose reason is COST_CORRECTION or by matching a supplier bill with its receipt lines. No other credit ever touches inventory. Each correction names receipt lines; for each one the valued history says where those goods are now: what the entity still holds changes value where it is, in stock or in transit, and what already left (sold, lost, returned, sent to another entity) goes to the PURCHASE_COST_VARIANCE account. Under FIFO the layers of the receipt decide what is still held, which need not be the same physical units or IMEI; under weighted average every exit took its proportion of the pool. Nothing is recalculated backwards and no posted entry is rewritten: an adjustment is a new dated event with one ledger entry, and it is undone by another adjustment that names it. A receipt line is matched with one bill line at a time, a credit adjusts once, and a correction never leaves goods with a negative cost. Receipts older than the ledger have no cost in it: 409 COST_SOURCE_NOT_VALUED.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedLines"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/receipt-matching":{"get":{"operationId":"tenantPurchasesGetBillsByIdReceiptMatching","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read. A purchase cost corrected after the goods were received, by a supplier credit whose reason is COST_CORRECTION or by matching a supplier bill with its receipt lines. No other credit ever touches inventory. Each correction names receipt lines; for each one the valued history says where those goods are now: what the entity still holds changes value where it is, in stock or in transit, and what already left (sold, lost, returned, sent to another entity) goes to the PURCHASE_COST_VARIANCE account. Under FIFO the layers of the receipt decide what is still held, which need not be the same physical units or IMEI; under weighted average every exit took its proportion of the pool. Nothing is recalculated backwards and no posted entry is rewritten: an adjustment is a new dated event with one ledger entry, and it is undone by another adjustment that names it. A receipt line is matched with one bill line at a time, a credit adjusts once, and a correction never leaves goods with a negative cost. Receipts older than the ledger have no cost in it: 409 COST_SOURCE_NOT_VALUED.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptMatching"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/receipt-matches":{"post":{"operationId":"tenantPurchasesPostBillsByIdReceiptMatches","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. States which receipt lines each line of an issued bill invoices; equal amounts are matched and post nothing, a different amount becomes a cost adjustment against the purchase bridge. A purchase cost corrected after the goods were received, by a supplier credit whose reason is COST_CORRECTION or by matching a supplier bill with its receipt lines. No other credit ever touches inventory. Each correction names receipt lines; for each one the valued history says where those goods are now: what the entity still holds changes value where it is, in stock or in transit, and what already left (sold, lost, returned, sent to another entity) goes to the PURCHASE_COST_VARIANCE account. Under FIFO the layers of the receipt decide what is still held, which need not be the same physical units or IMEI; under weighted average every exit took its proportion of the pool. Nothing is recalculated backwards and no posted entry is rewritten: an adjustment is a new dated event with one ledger entry, and it is undone by another adjustment that names it. A receipt line is matched with one bill line at a time, a credit adjusts once, and a correction never leaves goods with a negative cost. Receipts older than the ledger have no cost in it: 409 COST_SOURCE_NOT_VALUED.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptMatchInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptMatchResult"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/receipt-matches/{adjustmentId}/reverse":{"post":{"operationId":"tenantPurchasesPostBillsByIdReceiptMatchesByAdjustmentIdReverse","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.approve. Undoes one matching with its opposite adjustment, distributed as the goods stand today, and frees its receipt lines. A matched bill cannot be voided before this. A purchase cost corrected after the goods were received, by a supplier credit whose reason is COST_CORRECTION or by matching a supplier bill with its receipt lines. No other credit ever touches inventory. Each correction names receipt lines; for each one the valued history says where those goods are now: what the entity still holds changes value where it is, in stock or in transit, and what already left (sold, lost, returned, sent to another entity) goes to the PURCHASE_COST_VARIANCE account. Under FIFO the layers of the receipt decide what is still held, which need not be the same physical units or IMEI; under weighted average every exit took its proportion of the pool. Nothing is recalculated backwards and no posted entry is rewritten: an adjustment is a new dated event with one ledger entry, and it is undone by another adjustment that names it. A receipt line is matched with one bill line at a time, a credit adjusts once, and a correction never leaves goods with a negative cost. Receipts older than the ledger have no cost in it: 409 COST_SOURCE_NOT_VALUED.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"adjustmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostReversalInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptMatchResult"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/ledgers":{"get":{"operationId":"tenantAccountingGetLedgers","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerStatusPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantAccountingPostLedgers","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ledger"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/ledgers/{id}":{"put":{"operationId":"tenantAccountingPutLedgersById","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ledger"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/accounts":{"get":{"operationId":"tenantAccountingGetAccounts","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"status","in":"query","schema":{"enum":["ACTIVE","ARCHIVED"]}},{"name":"type","in":"query","schema":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]}},{"name":"kind","in":"query","schema":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantAccountingPostAccounts","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/accounts/{id}":{"put":{"operationId":"tenantAccountingPutAccountsById","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/mappings":{"get":{"operationId":"tenantAccountingGetMappings","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingMappingPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantAccountingPutMappings","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingMappingsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingMappingsReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/fiscal-years":{"get":{"operationId":"tenantAccountingGetFiscalYears","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiscalYearPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantAccountingPostFiscalYears","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiscalYearInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiscalYearReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/fiscal-years/{id}/close":{"post":{"operationId":"tenantAccountingPostFiscalYearsByIdClose","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.close. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiscalYearClosed"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/periods/{id}/close":{"post":{"operationId":"tenantAccountingPostPeriodsByIdClose","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.close. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingPeriodReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/periods/{id}/reopen":{"post":{"operationId":"tenantAccountingPostPeriodsByIdReopen","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.close. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingPeriodReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/entries":{"get":{"operationId":"tenantAccountingGetEntries","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"status","in":"query","schema":{"enum":["DRAFT","POSTED","REJECTED"]}},{"name":"from","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: first day of the ledger."},{"name":"to","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: today in the ledger time zone."},{"name":"sourceId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"accountId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntryPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantAccountingPostEntries","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.post. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntryInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntry"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/entries/{id}":{"get":{"operationId":"tenantAccountingGetEntriesById","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntry"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/entries/{id}/post":{"post":{"operationId":"tenantAccountingPostEntriesByIdPost","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.approve; never the user who prepared the entry. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntry"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/entries/{id}/reject":{"post":{"operationId":"tenantAccountingPostEntriesByIdReject","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.approve; never the user who prepared the entry. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationVersionInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntry"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/entries/{id}/reverse":{"post":{"operationId":"tenantAccountingPostEntriesByIdReverse","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.post and accounting.approve. Only manual and opening entries: the entry of an operation is reversed by voiding the operation. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntryReversalInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntry"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/operations/{id}/entries":{"get":{"operationId":"tenantAccountingGetOperationsByIdEntries","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. `id` is the operation: an invoice, payment, credit, sales order, counter session or receipt, purchase order or receipt, transfer or import order, supplier return, settlement or inventory movement. Its own entries, those of what hangs from it and their reversals. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntryRelated"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/general-ledger":{"get":{"operationId":"tenantAccountingGetGeneralLedger","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"accountId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"from","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: first day of the ledger."},{"name":"to","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: today in the ledger time zone."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountLedger"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/trial-balance":{"get":{"operationId":"tenantAccountingGetTrialBalance","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"from","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: first day of the ledger."},{"name":"to","in":"query","schema":{"type":"string","format":"date","description":"Calendar day."},"description":"Default: today in the ledger time zone."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrialBalance"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/reconciliation":{"get":{"operationId":"tenantAccountingGetReconciliation","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Reconciliation"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/accounting/settlements":{"get":{"operationId":"tenantAccountingGetSettlements","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantAccountingPostSettlements","tags":["Accounting"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.post. Double-entry books per legal entity, in its base currency. Opening a ledger turns accounting on for one legal entity from `startsOn`: from then on every covered operation of that entity (invoices, payments, applications, credits, refunds, counter collections, cash movements, settlements and valued stock movements) writes its entry in the same transaction or does not happen. An entity without a ledger keeps no books and behaves as before. Debits equal credits to the last unit of the currency; amounts are exact and never floats. A posted entry is immutable: it is corrected by a linked mirror entry. One entry per event, enforced by a unique key. A closed period refuses every new entry dated in it. Manual and opening entries are proposals until a different user approves them. Billing, delivery and collection are separate facts: an invoice never recognises revenue by itself, a goods receipt and its bill never count inventory twice, and an application distributes money or credit already booked without bringing money in. Card vouchers and cheques wait in clearing accounts until a settlement records the real net and fee. No tax, fiscal policy, exchange rate or cost is ever invented: what is missing blocks the operation with a specific code. Writes are idempotent, tenant scoped and audited.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settlement"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/pools":{"get":{"operationId":"tenantValuationGetPools","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"variantId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationPoolPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/entries":{"get":{"operationId":"tenantValuationGetEntries","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"variantId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationEntryPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/policies":{"get":{"operationId":"tenantValuationGetPolicies","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.read and catalog.read. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"legalEntityId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Legal entity whose books are read. 409 ACCOUNTING_SETUP_REQUIRED when it keeps none."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationPolicyPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"operationId":"tenantValuationPutPolicies","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure. Only while the entity values BY_PRODUCT and the product has no valued movement. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationPolicyInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationPolicyReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/transitions":{"post":{"operationId":"tenantValuationPostTransitions","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure and accounting.approve. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationTransitionInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValuationTransition"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/valuation/opening-balances":{"post":{"operationId":"tenantValuationPostOpeningBalances","tags":["Valuation"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions accounting.configure and accounting.post. Values, at the stated cost, the stock the entity already held and that has no value yet; 409 when nothing is left to value. The company keeps a default method (WEIGHTED_AVERAGE, FIFO or BY_PRODUCT): a legal entity inherits it when its books open without stating one, and may state a different one. The effective policy belongs to the entity and, in BY_PRODUCT, to each product; changing the company default never changes a ledger that exists. Inventory valuation per legal entity and variant: moving weighted average or FIFO cost layers. The entity chooses one method, or BY_PRODUCT, where each product chooses before its stock can be valued; variants inherit the product policy and keep independent costs, and every warehouse of the entity shares it. Stock in hand and stock in a transit warehouse are valued apart. Costs come from the purchase order line, from the cost stated on a manual entry of stock, or travel with the stock from the pool it leaves; they are never sale prices, never estimated and never taken as zero. FIFO decides which costs are consumed, not which physical unit or IMEI must be delivered; every serialized movement keeps its unit identity. Values are rounded half up to the minor unit of the currency, and taking everything takes every cent. After valued movements the method changes only through a dated, audited transition that carries the current value over and rewrites nothing. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpeningStockInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpeningStock"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, duplicate, or a specific block: ACCOUNTING_SETUP_REQUIRED (no ledger, unmapped key, account of the wrong kind), ACCOUNTING_PERIOD_CLOSED, ACCOUNTING_CURRENCY_UNSUPPORTED, ACCOUNTING_AMOUNT_PRECISION, VALUATION_METHOD_REQUIRED, VALUATION_COST_REQUIRED, SEPARATION_OF_DUTIES, PAYMENT_ACCOUNT_INVALID (the account stated is not an active account of the entity that fits the method), CASH_SESSION_REQUIRED, CASH_INSUFFICIENT, COST_SOURCE_NOT_VALUED, COST_ADJUSTMENT_EXCEEDS_COST, COST_MATCH_MISMATCH","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/pos/sessions/{id}/cash-movements":{"get":{"operationId":"tenantPosGetSessionsByIdCashMovements","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. Cash that enters or leaves a till outside a sale needs pos.cash.move and is booked against another cash or bank account, or an account accounting opened for till movements (cashCounterpart). Cash handed back for a customer credit leaves the till through the refund itself: it lowers the expected cash and posts one entry, the refund. Human Supabase USER only. Counter collection with payment components: cash, transfer, debit or credit card, cheque and other configured methods, alone or mixed. Collections made on an external terminal or bank are recorded; no acquirer is contacted, no charge is made and no card number or security code is accepted or stored. Each component records amount, currency, method, destination account, status and reference; the components add up to the order total exactly, and delivery stays complete: no credit or partial delivery. Change is given only in cash. The cash count expects only cash that physically stayed in the till: opening amount, cash portions of sales and cash movements; cards and transfers are shown apart. When the entity keeps books the collection posts one entry in the same transaction. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosCashMovementPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash the till does not hold, or ACCOUNTING_SETUP_REQUIRED / ACCOUNTING_PERIOD_CLOSED","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"tenantPosPostSessionsByIdCashMovements","tags":["POS"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create and pos.cash.move; only the operator of the open session. 409 CASH_INSUFFICIENT when the till does not hold the cash, 409 PAYMENT_ACCOUNT_INVALID when the account is not one a till movement may use. Cash that enters or leaves a till outside a sale needs pos.cash.move and is booked against another cash or bank account, or an account accounting opened for till movements (cashCounterpart). Cash handed back for a customer credit leaves the till through the refund itself: it lowers the expected cash and posts one entry, the refund. Human Supabase USER only. Counter collection with payment components: cash, transfer, debit or credit card, cheque and other configured methods, alone or mixed. Collections made on an external terminal or bank are recorded; no acquirer is contacted, no charge is made and no card number or security code is accepted or stored. Each component records amount, currency, method, destination account, status and reference; the components add up to the order total exactly, and delivery stays complete: no credit or partial delivery. Change is given only in cash. The cash count expects only cash that physically stayed in the till: opening amount, cash portions of sales and cash movements; cards and transfers are shown apart. When the entity keeps books the collection posts one entry in the same transaction. Writes are idempotent and tenant scoped.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosCashMovementInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosCashMovement"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version, state, cash the till does not hold, or ACCOUNTING_SETUP_REQUIRED / ACCOUNTING_PERIOD_CLOSED","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/invoices/{id}/confirm-delivery":{"post":{"operationId":"tenantSalesPostInvoicesByIdConfirmDelivery","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.create, pricing.read, inventory.adjust (403 FULFILMENT_PERMISSION_DENIED names the ones lacking). An invoice carries the physical units of its serialized lines. A supplier bill without a purchase order types the devices it will receive (IMEI 1, IMEI 2, serial number: two IMEI of one phone are one unit); a bill of a purchase order names units that order already received; a sales invoice without an order names the units its direct sale will deliver. Saving any of it reserves and moves nothing, and a draft may be incomplete; posting is not: each serialized line names exactly as many units as it bills (409 UNIT_COUNT_MISMATCH, with `required` and `identified` at the place of each line), and issuing alone is refused for an invoice with no order behind it (409 FULFILMENT_REQUIRED). Confirming with the receipt writes, in one transaction, the purchase with its usual documents (order, approval, receipt in the bill warehouse), one unit and one entry movement per device, the units on the bill lines, and the issue; confirming with the delivery writes the sale with its usual documents (order at the list price, confirmation that reserves the chosen units, delivery), and the issue; for an invoice of an order already confirmed it delivers what that order reserved. Valuation and accounting follow from those movements and from the issue as they always do, and a failure leaves nothing. A sales invoice of an order shows the units the order reserved or delivered and, from the instant it is issued, keeps them as its own: they are never chosen again, they stay on the invoice whatever becomes of the order (a unit its order let go afterwards reads RELEASED), and a sale collected at the register is never delivered, collected or posted twice. Whoever lacks what a receipt or a delivery takes beyond writing the invoice is told which permissions (403 FULFILMENT_PERMISSION_DENIED, one place per permission under `/permissions`): issuing alone is never the alternative. Quantity articles and services have no units here. No taxes, fiscal issue or returns.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceFulfilmentInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceFulfilmentReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version or state, or a specific block with the place of each problem in `errors`: UNIT_IDENTIFIER_TAKEN, UNIT_COUNT_MISMATCH, UNIT_NOT_ELIGIBLE, FULFILMENT_INCOMPLETE, FULFILMENT_PRICE_MISMATCH, FULFILMENT_ORDER_NUMBER_TAKEN, FULFILMENT_REQUIRED, and the accounting and valuation blocks of a receipt or a delivery","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/confirm-receipt":{"post":{"operationId":"tenantPurchasesPostBillsByIdConfirmReceipt","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create, purchases.approve, inventory.adjust (403 FULFILMENT_PERMISSION_DENIED names the ones lacking). An invoice carries the physical units of its serialized lines. A supplier bill without a purchase order types the devices it will receive (IMEI 1, IMEI 2, serial number: two IMEI of one phone are one unit); a bill of a purchase order names units that order already received; a sales invoice without an order names the units its direct sale will deliver. Saving any of it reserves and moves nothing, and a draft may be incomplete; posting is not: each serialized line names exactly as many units as it bills (409 UNIT_COUNT_MISMATCH, with `required` and `identified` at the place of each line), and issuing alone is refused for an invoice with no order behind it (409 FULFILMENT_REQUIRED). Confirming with the receipt writes, in one transaction, the purchase with its usual documents (order, approval, receipt in the bill warehouse), one unit and one entry movement per device, the units on the bill lines, and the issue; confirming with the delivery writes the sale with its usual documents (order at the list price, confirmation that reserves the chosen units, delivery), and the issue; for an invoice of an order already confirmed it delivers what that order reserved. Valuation and accounting follow from those movements and from the issue as they always do, and a failure leaves nothing. A sales invoice of an order shows the units the order reserved or delivered and, from the instant it is issued, keeps them as its own: they are never chosen again, they stay on the invoice whatever becomes of the order (a unit its order let go afterwards reads RELEASED), and a sale collected at the register is never delivered, collected or posted twice. Whoever lacks what a receipt or a delivery takes beyond writing the invoice is told which permissions (403 FULFILMENT_PERMISSION_DENIED, one place per permission under `/permissions`): issuing alone is never the alternative. Quantity articles and services have no units here. No taxes, fiscal issue or returns.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceFulfilmentInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceFulfilmentReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version or state, or a specific block with the place of each problem in `errors`: UNIT_IDENTIFIER_TAKEN, UNIT_COUNT_MISMATCH, UNIT_NOT_ELIGIBLE, FULFILMENT_INCOMPLETE, FULFILMENT_PRICE_MISMATCH, FULFILMENT_ORDER_NUMBER_TAKEN, FULFILMENT_REQUIRED, and the accounting and valuation blocks of a receipt or a delivery","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/bills/{id}/received-units":{"post":{"operationId":"tenantPurchasesPostBillsByIdReceivedUnits","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.create. Names, on a bill issued before units were required, units its purchase order received; the bill, its amounts and its version do not change. A bill is no longer issued short of units, and a receipt adds none to an issued bill by itself. An invoice carries the physical units of its serialized lines. A supplier bill without a purchase order types the devices it will receive (IMEI 1, IMEI 2, serial number: two IMEI of one phone are one unit); a bill of a purchase order names units that order already received; a sales invoice without an order names the units its direct sale will deliver. Saving any of it reserves and moves nothing, and a draft may be incomplete; posting is not: each serialized line names exactly as many units as it bills (409 UNIT_COUNT_MISMATCH, with `required` and `identified` at the place of each line), and issuing alone is refused for an invoice with no order behind it (409 FULFILMENT_REQUIRED). Confirming with the receipt writes, in one transaction, the purchase with its usual documents (order, approval, receipt in the bill warehouse), one unit and one entry movement per device, the units on the bill lines, and the issue; confirming with the delivery writes the sale with its usual documents (order at the list price, confirmation that reserves the chosen units, delivery), and the issue; for an invoice of an order already confirmed it delivers what that order reserved. Valuation and accounting follow from those movements and from the issue as they always do, and a failure leaves nothing. A sales invoice of an order shows the units the order reserved or delivered and, from the instant it is issued, keeps them as its own: they are never chosen again, they stay on the invoice whatever becomes of the order (a unit its order let go afterwards reads RELEASED), and a sale collected at the register is never delivered, collected or posted twice. Whoever lacks what a receipt or a delivery takes beyond writing the invoice is told which permissions (403 FULFILMENT_PERMISSION_DENIED, one place per permission under `/permissions`): issuing alone is never the alternative. Quantity articles and services have no units here. No taxes, fiscal issue or returns.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUIDv4/v7. Fresh user/membership/permissions before replay."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReceivedUnitsInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceUnitsReceipt"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version or state, or a specific block with the place of each problem in `errors`: UNIT_IDENTIFIER_TAKEN, UNIT_COUNT_MISMATCH, UNIT_NOT_ELIGIBLE, FULFILMENT_INCOMPLETE, FULFILMENT_PRICE_MISMATCH, FULFILMENT_ORDER_NUMBER_TAKEN, FULFILMENT_REQUIRED, and the accounting and valuation blocks of a receipt or a delivery","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/purchases/orders/{id}/received-units":{"get":{"operationId":"tenantPurchasesGetOrdersByIdReceivedUnits","tags":["Procurement"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions purchases.read, inventory.read, inventory.serials.read. An invoice carries the physical units of its serialized lines. A supplier bill without a purchase order types the devices it will receive (IMEI 1, IMEI 2, serial number: two IMEI of one phone are one unit); a bill of a purchase order names units that order already received; a sales invoice without an order names the units its direct sale will deliver. Saving any of it reserves and moves nothing, and a draft may be incomplete; posting is not: each serialized line names exactly as many units as it bills (409 UNIT_COUNT_MISMATCH, with `required` and `identified` at the place of each line), and issuing alone is refused for an invoice with no order behind it (409 FULFILMENT_REQUIRED). Confirming with the receipt writes, in one transaction, the purchase with its usual documents (order, approval, receipt in the bill warehouse), one unit and one entry movement per device, the units on the bill lines, and the issue; confirming with the delivery writes the sale with its usual documents (order at the list price, confirmation that reserves the chosen units, delivery), and the issue; for an invoice of an order already confirmed it delivers what that order reserved. Valuation and accounting follow from those movements and from the issue as they always do, and a failure leaves nothing. A sales invoice of an order shows the units the order reserved or delivered and, from the instant it is issued, keeps them as its own: they are never chosen again, they stay on the invoice whatever becomes of the order (a unit its order let go afterwards reads RELEASED), and a sale collected at the register is never delivered, collected or posted twice. Whoever lacks what a receipt or a delivery takes beyond writing the invoice is told which permissions (403 FULFILMENT_PERMISSION_DENIED, one place per permission under `/permissions`): issuing alone is never the alternative. Quantity articles and services have no units here. No taxes, fiscal issue or returns.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"variantId","in":"query","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedUnitPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Version or state, or a specific block with the place of each problem in `errors`: UNIT_IDENTIFIER_TAKEN, UNIT_COUNT_MISMATCH, UNIT_NOT_ELIGIBLE, FULFILMENT_INCOMPLETE, FULFILMENT_PRICE_MISMATCH, FULFILMENT_ORDER_NUMBER_TAKEN, FULFILMENT_REQUIRED, and the accounting and valuation blocks of a receipt or a delivery","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/inventory/units/{id}/trace":{"get":{"operationId":"tenantSerialsGetUnitsByIdTrace","tags":["Inventory"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions inventory.read, inventory.serials.read. The history of one physical unit: every movement and every reservation event that exists for it, in causal order, each with where it happened and the documents behind it. Documents are related by identifiers only. Each document is named only to a reader who holds the read permission of its module at the time of the request (purchases.read for bills, purchase orders, receipts and supplier returns; sales.read for sales invoices, sales orders and till receipts; accounting.read for journal entries; transfer and import orders with inventory.read). Without it the fact stays and the module is listed in `withheld`; opening a document is authorised again by its own endpoint. A unit of another company is not found.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnitTrace"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used by this read","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/tenants/{tenantId}/sales/price-adjustments":{"get":{"operationId":"tenantSalesGetPriceAdjustments","tags":["Sales"],"security":[{"SupabaseBearer":[]}],"description":"Human Supabase USER only; permissions sales.read. A sale line is priced by its list unless a person agrees another price: the unit price itself or a discount on the list price, never both. Agreeing a price takes sales.price.override, besides the permission to write the document, and a reason; the server checks it and records who changed the price, the price before, the list price and why. Without the permission the list price is used. An agreed price is a snapshot: an accepted quotation hands it to its order, the order keeps it when it is confirmed and delivered, its invoice bills it and the register collects it; a later change of the price list changes none of them, and the price list itself is never changed by a sale. A line at the list price keeps taking the list price in force when its order is confirmed, as before. The invoice and the order written from it carry the same quantities, agreed prices, currency and total. An agreed price changes the sale amount only: never the cost or the valuation of what is sold. API clients state no prices. This read lists every change of an agreed price of one sale document (a quotation, a sales order or a sales invoice) together with those of the documents it comes from or was written into, oldest first.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},{"name":"documentId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceAdjustmentPage"}}}},"400":{"description":"Invalid request/idempotency key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing/invalid Supabase JWT","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Wrong identity family or permissions","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Unknown tenant resource","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Not used by this read","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate/quota exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Runtime/auth/governance unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/onboarding":{"get":{"operationId":"onboardingState","tags":["Onboarding"],"security":[{"SupabaseBearer":[]}],"description":"Active human identity only. Own immutable completion receipt and server-owned setup/plan options. No business access or global grants from signup.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingState"}}}},"400":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"operationId":"completeOnboarding","tags":["Onboarding"],"security":[{"SupabaseBearer":[]}],"description":"Deliberate atomic creation of the account’s first self-service tenant, its local administrator, entity, branch, warehouse, internal list, empty ledger and selected fiscal year. Opening date must be within a fiscal range of at most 366 days; clipped monthly periods cover it exactly. User-bound durable idempotency: same key+input replays; changed input or another key after creation returns 409. Paid selection is PENDING_PAYMENT with FREE entitlements until verified activation; no payment is collected. No caller-supplied identity, IDs, roles, price or entitlement. Other memberships and legacy companies are unchanged.","parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingInput"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingReceipt"}}}},"400":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid input, identity, idempotency, limit or availability","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/users":{"get":{"operationId":"listPlatformUsers","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[{"in":"query","name":"q","schema":{"type":"string","maxLength":100}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"in":"query","name":"cursor","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformUsers"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/plans":{"get":{"operationId":"listPlatformPlans","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformPlans"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/tenants/{tenantId}":{"get":{"operationId":"getPlatformCompany","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[{"in":"path","name":"tenantId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformCompanyDetail"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/tenants/{tenantId}/members":{"get":{"operationId":"listGlobalCompanyMembers","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[{"in":"path","name":"tenantId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformMembers"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/tenants/{tenantId}/roles":{"get":{"operationId":"listGlobalCompanyRoles","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Active human platform administrator only, rechecked inside the database transaction. No authorization from email or client metadata. Tenant isolation still applies to business records.","parameters":[{"in":"path","name":"tenantId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformRoles"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/platform/tenants/{tenantId}/plan":{"put":{"operationId":"assignComplimentaryPlan","tags":["Platform administration"],"security":[{"SupabaseBearer":[]}],"description":"Explicit complimentary assignment by an active global administrator. No charge or membership/role change. Expected subscription version, durable tenant-bound idempotency, serialized quotas, retained serial trace and append-only assignment history. FREE/BASIC are refused when serialized inventory exists; a downgrade cannot remove data or exceed its limits. Self-service paid requests remain pending until separately activated.","parameters":[{"in":"path","name":"tenantId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplimentaryPlanInput"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplimentaryPlanAssignment"}}}},"400":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Invalid request, missing global authority, stale version, quota or unavailable service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}}},"components":{"securitySchemes":{"SupabaseBearer":{"type":"http","scheme":"bearer","bearerFormat":"Supabase access JWT"},"PlatformApiKey":{"type":"http","scheme":"bearer","bearerFormat":"bp_test_UUIDv7.256-bit-secret or bp_live_UUIDv7.256-bit-secret","description":"Server-side integration credential, environment-bound. Tenant derives from key; never use in a public browser bundle."}},"schemas":{"ProblemDetails":{"type":"object","additionalProperties":false,"required":["type","status","code","title","detail","requestId"],"properties":{"type":{"const":"about:blank"},"status":{"type":"integer"},"code":{"type":"string"},"title":{"type":"string"},"detail":{"type":"string"},"requestId":{"type":"string","format":"uuid"},"errors":{"type":"array","maxItems":200,"description":"Where each problem is, for the codes that can say it: a JSON pointer into the request or the record (`/items/0/devices/1/imei1`) and the reason. A line of a serialized article that is short of units also says how many it bills and how many are identified. Never a value typed by the user, and never an identifier of a unit.","items":{"type":"object","additionalProperties":false,"required":["pointer","code"],"properties":{"pointer":{"type":"string"},"code":{"type":"string"},"required":{"type":"integer","minimum":0,"maximum":1000,"description":"For a line short of units (UNITS_DIFFER_FROM_QUANTITY, RECEIPT_REQUIRED, DELIVERY_REQUIRED): how many units the line bills."},"identified":{"type":"integer","minimum":0,"maximum":1000,"description":"For the same line: how many units are identified and linked to it. Given to every reader of the document; no IMEI or serial number is."}}}}}},"UserPrincipal":{"type":"object","additionalProperties":false,"required":["kind","userId","requestId"],"properties":{"kind":{"const":"USER"},"userId":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"}}},"CurrentUser":{"type":"object","additionalProperties":false,"required":["principal","user","memberships"],"properties":{"principal":{"$ref":"#/components/schemas/UserPrincipal"},"user":{"type":"object","additionalProperties":false,"required":["id","displayName","status"],"properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"status":{"const":"ACTIVE"}}},"memberships":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","tenantId","userId","status"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"status":{"const":"ACTIVE"}}}},"platformAdministrator":{"type":"boolean","description":"Explicit active operator grant; not inferred from email or JWT metadata."}}},"AuthorizedUserContext":{"type":"object","additionalProperties":false,"required":["principal","tenantId","membershipId","permissions"],"properties":{"principal":{"$ref":"#/components/schemas/UserPrincipal"},"tenantId":{"type":"string","format":"uuid"},"membershipId":{"type":["string","null"],"format":"uuid"},"permissions":{"type":"array","items":{"type":"string"}},"accessSource":{"type":"string","enum":["PLATFORM_ADMIN"]}}},"ApiClient":{"type":"object","additionalProperties":false,"required":["id","tenantId","name","environment","status","createdBy","createdAt","updatedAt","scopes"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"name":{"type":"string"},"environment":{"enum":["test","live"]},"status":{"enum":["ACTIVE","DISABLED"]},"createdBy":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"scopes":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","enum":["catalog.read","catalog.write","pricing.read","pricing.write","inventory.read","inventory.serials.read","inventory.write","customers.read","customers.write","suppliers.read","suppliers.write","purchases.read","purchases.write","sales.read","sales.write","webhooks.manage"]}}}},"ApiKeyMetadata":{"type":"object","additionalProperties":false,"required":["id","tenantId","apiClientId","prefix","last4","environment","status","createdAt","createdBy","expiresAt","lastUsedAt","revokedAt","revokedBy"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"apiClientId":{"type":"string","format":"uuid"},"prefix":{"type":"string"},"last4":{"type":"string","minLength":4,"maxLength":4},"environment":{"enum":["test","live"]},"status":{"enum":["ACTIVE","REVOKED","EXPIRED"]},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"},"expiresAt":{"type":"string","format":"date-time"},"lastUsedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revokedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revokedBy":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}}},"IssuedApiKey":{"type":"object","additionalProperties":false,"required":["key","token"],"properties":{"key":{"$ref":"#/components/schemas/ApiKeyMetadata"},"token":{"type":"string","writeOnly":false,"description":"One-time bearer credential. Never returned by GET or stored as plaintext."}}},"ApiClientPrincipal":{"type":"object","additionalProperties":false,"required":["kind","clientId","keyId","requestId"],"properties":{"kind":{"const":"API_CLIENT"},"clientId":{"type":"string","format":"uuid"},"keyId":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"}}},"ApiClientContext":{"type":"object","additionalProperties":false,"required":["principal","tenantId","scopes"],"properties":{"principal":{"$ref":"#/components/schemas/ApiClientPrincipal"},"tenantId":{"type":"string","format":"uuid"},"scopes":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","enum":["catalog.read","catalog.write","pricing.read","pricing.write","inventory.read","inventory.serials.read","inventory.write","customers.read","customers.write","suppliers.read","suppliers.write","purchases.read","purchases.write","sales.read","sales.write","webhooks.manage"]}}}},"AuditLog":{"type":"object","additionalProperties":false,"required":["id","tenantId","requestId","resourceId","actorType","actorId","operation","resourceType","ipAddress","userAgent","metadata","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"},"resourceId":{"type":"string","format":"uuid"},"actorType":{"enum":["USER","API_CLIENT","SYSTEM"]},"actorId":{"type":"string"},"operation":{"type":"string"},"resourceType":{"enum":["ROLE","MEMBERSHIP","API_CLIENT","API_KEY","API_REQUEST","WEBHOOK_ENDPOINT","WEBHOOK_EVENT","WEBHOOK_DELIVERY","CATALOG_PRODUCT","CATALOG_VARIANT","CATALOG_LOOKUP","CATALOG_MEDIA","PRICE_LIST","PRICE","WAREHOUSE","WAREHOUSE_LOCATION","INVENTORY_MOVEMENT","INVENTORY_RESERVATION","INVENTORY_UNIT","SUPPLIER","PURCHASE_ORDER","GOODS_RECEIPT","CUSTOMER","SALES_ORDER","POS_REGISTER","POS_SESSION","POS_RECEIPT"]},"ipAddress":{"type":["string","null"]},"userAgent":{"type":["string","null"],"description":"Normalized family/major version; no raw UA"},"metadata":{"type":"object","additionalProperties":false,"required":["result"],"properties":{"result":{"enum":["SUCCESS","ADMITTED","DENIED"]},"reason":{"enum":["RATE_LIMITED","QUOTA_EXCEEDED","PUBLIC_API_DISABLED"]},"responseCode":{"type":"integer"},"keyId":{"type":"string","format":"uuid"}}},"createdAt":{"type":"string","format":"date-time"}}},"AuditPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"nextCursor":{"type":["string","null"],"format":"uuid"}}},"WebhookInput":{"type":"object","additionalProperties":false,"required":["name","url","status","subscriptions"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"url":{"type":"string","format":"uri","maxLength":2048,"description":"HTTPS on port 443, DNS hostname only; no userinfo, query or fragment. Public DNS checked and pinned per attempt."},"status":{"enum":["ACTIVE","DISABLED"]},"subscriptions":{"type":"array","minItems":1,"maxItems":42,"uniqueItems":true,"items":{"enum":["webhook.test","inventory.updated","sale.created","sale.completed","catalog.product.created","catalog.product.updated","catalog.product.archived","catalog.product.deleted","catalog.variant.created","catalog.variant.updated","catalog.variant.archived","catalog.media.created","catalog.media.updated","catalog.media.archived","catalog.lookup.created","catalog.lookup.updated","catalog.lookup.archived","pricing.list.created","pricing.list.updated","pricing.list.archived","pricing.price.created","pricing.price.updated","pricing.price.archived","inventory.warehouse.created","inventory.warehouse.updated","inventory.warehouse.archived","inventory.location.created","inventory.location.updated","inventory.location.archived","procurement.supplier.created","procurement.supplier.updated","procurement.supplier.archived","procurement.order.created","procurement.order.updated","procurement.order.approved","procurement.order.cancelled","procurement.receipt.created","sale.updated","sale.confirmed","sale.cancelled","sales.customer.created","sales.customer.updated","sales.customer.archived","pos.register.created","pos.register.archived","pos.session.opened","pos.session.closed","pos.receipt.created"]}}}},"WebhookEndpoint":{"allOf":[{"$ref":"#/components/schemas/WebhookInput"},{"type":"object","required":["id","tenantId","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}]},"WebhookCredential":{"type":"object","additionalProperties":false,"required":["id","signingSecret"],"properties":{"id":{"type":"string","format":"uuid"},"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"},"signingSecret":{"type":"string","pattern":"^whsec_[A-Za-z0-9_-]{43}$","description":"Shown once; never persisted as plaintext or replayed. HMAC key is this complete UTF-8 string."}}},"WebhookTestReceipt":{"type":"object","additionalProperties":false,"required":["id","deliveryIds"],"properties":{"id":{"type":"string","format":"uuid"},"deliveryIds":{"type":"array","items":{"type":"string","format":"uuid"}}}},"WebhookDelivery":{"type":"object","additionalProperties":false,"required":["id","tenantId","endpointId","eventId","status","attemptCount","lastAttemptAt","nextAttemptAt","responseStatus","responseExcerpt","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"endpointId":{"type":"string","format":"uuid"},"eventId":{"type":"string","format":"uuid"},"status":{"enum":["PENDING","SENDING","RETRY","DELIVERED","FAILED","CANCELLED"]},"attemptCount":{"type":"integer","minimum":0,"maximum":5},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"nextAttemptAt":{"type":["string","null"],"format":"date-time"},"responseStatus":{"type":["integer","null"]},"responseExcerpt":{"type":["string","null"],"description":"Safe diagnostic code only; never receiver response bodies."},"createdAt":{"type":"string","format":"date-time"}}},"WebhookEnvelope":{"type":"object","additionalProperties":false,"required":["event_id","event_type","tenant_id","occurred_at","payload"],"properties":{"event_id":{"type":"string","format":"uuid"},"event_type":{"enum":["webhook.test","inventory.updated","sale.created","sale.completed","catalog.product.created","catalog.product.updated","catalog.product.archived","catalog.product.deleted","catalog.variant.created","catalog.variant.updated","catalog.variant.archived","catalog.media.created","catalog.media.updated","catalog.media.archived","catalog.lookup.created","catalog.lookup.updated","catalog.lookup.archived","pricing.list.created","pricing.list.updated","pricing.list.archived","pricing.price.created","pricing.price.updated","pricing.price.archived","inventory.warehouse.created","inventory.warehouse.updated","inventory.warehouse.archived","inventory.location.created","inventory.location.updated","inventory.location.archived","procurement.supplier.created","procurement.supplier.updated","procurement.supplier.archived","procurement.order.created","procurement.order.updated","procurement.order.approved","procurement.order.cancelled","procurement.receipt.created","sale.updated","sale.confirmed","sale.cancelled","sales.customer.created","sales.customer.updated","sales.customer.archived","pos.register.created","pos.register.archived","pos.session.opened","pos.session.closed","pos.receipt.created"]},"tenant_id":{"type":"string","format":"uuid"},"occurred_at":{"type":"string","format":"date-time"},"payload":{"type":"object"}}},"CatalogProductInput":{"type":"object","additionalProperties":false,"required":["name","productType","unitOfMeasure"],"properties":{"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":["string","null"],"maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$","description":"Web identifier, unique per company and kept reserved after archiving. Optional. Omitted or null on creation: generated from the name (accents and symbols removed, words joined by hyphens, at most 160 characters) and, when taken, completed with -2, -3… Stated: used as given, 409 when taken. Omitted or null on update: the product keeps its slug; renaming a product never changes it."},"variantMode":{"enum":["SINGLE","MULTIPLE",null],"description":"SINGLE: an article sold as one SKU. MULTIPLE: an article that holds several versions of itself, each with its own SKU. Omitted or null on creation: MULTIPLE when more than one variant is created with the product, SINGLE otherwise. Omitted or null on update: unchanged. SINGLE is refused (409) while the product has more than one active variant."},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"manufacturerId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"trackInventory":{"type":"boolean","default":false},"trackSerials":{"type":"boolean","default":false},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true}}},"CatalogProduct":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","name","slug","productType","categoryId","brandId","manufacturerId","unitOfMeasure","trackInventory","trackSerials","publicationStatus","description","shortDescription","attributes","variantMode","variantCount","singleSku","singleVariantId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":"string","maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"variantMode":{"enum":["SINGLE","MULTIPLE"],"description":"What the product is in practice: MULTIPLE when it was declared so or has more than one active variant; SINGLE otherwise."},"variantCount":{"type":"integer","minimum":0,"description":"Active variants of the product. Zero: it has no SKU yet."},"singleSku":{"type":["string","null"],"description":"SKU of the only active variant when the product has exactly one; null otherwise."},"singleVariantId":{"type":["string","null"],"format":"uuid","description":"Id of the only active variant when the product has exactly one; null otherwise. Human reads only: API-key projections never carry it."},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"manufacturerId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"trackInventory":{"type":"boolean","default":false},"trackSerials":{"type":"boolean","default":false},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true}}},"CatalogProductPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogProduct"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogVariantInput":{"type":"object","additionalProperties":false,"required":["sku"],"properties":{"modelNumber":{"type":["string","null"],"maxLength":100},"barcode":{"type":["string","null"],"maxLength":100},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"sku":{"type":"string","maxLength":100,"pattern":"^[A-Z0-9][A-Z0-9_./-]{0,99}$"},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null]},"grade":{"enum":["A","B","C",null]},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"],"default":"NOT_APPLICABLE"},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true},"searchAliases":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":80},"default":[],"description":"Curated variant search aliases; NFKC/trim/space normalization, duplicates ignoring case/accents rejected. Public search may match aliases; arbitrary attributes are never indexed. Omitted in full variant replacement resets aliases to []."}}},"CatalogVariant":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","modelNumber","barcode","storage","color","sku","condition","grade","simType","attributes","productId","searchAliases"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"modelNumber":{"type":["string","null"],"maxLength":100},"barcode":{"type":["string","null"],"maxLength":100},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"sku":{"type":"string","maxLength":100,"pattern":"^[A-Z0-9][A-Z0-9_./-]{0,99}$"},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null]},"grade":{"enum":["A","B","C",null]},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"],"default":"NOT_APPLICABLE"},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"searchAliases":{"type":"array","maxItems":16,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":80},"default":[],"description":"Curated variant search aliases; NFKC/trim/space normalization, duplicates ignoring case/accents rejected. Public search may match aliases; arbitrary attributes are never indexed. Omitted in full variant replacement resets aliases to []."}}},"CatalogVariantPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogVariant"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogMediaInput":{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"Unsigned HTTPS URL, no userinfo, query or fragment. Metadata only; API and worker never fetch it."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"altText":{"type":["string","null"],"maxLength":300},"position":{"type":"integer","minimum":0,"maximum":10000,"default":0}}},"CatalogMedia":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","url","variantId","altText","position","productId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"url":{"type":"string","maxLength":2048,"format":"uri","description":"Unsigned HTTPS URL, no userinfo, query or fragment. Metadata only; API and worker never fetch it."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"altText":{"type":["string","null"],"maxLength":300},"position":{"type":"integer","minimum":0,"maximum":10000,"default":0},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogMediaPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogMedia"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogLookupInput":{"type":"object","additionalProperties":false,"required":["name","code"],"properties":{"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":64,"pattern":"^[A-Z][A-Z0-9_.-]*$"}}},"CatalogLookup":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","name","code"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":64,"pattern":"^[A-Z][A-Z0-9_.-]*$"}}},"CatalogLookupPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogLookup"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogUnitInput":{"type":"object","additionalProperties":false,"required":["name","code"],"properties":{"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"decimalPlaces":{"type":"integer","minimum":0,"maximum":6,"default":0}}},"CatalogUnit":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","name","code","decimalPlaces"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"decimalPlaces":{"type":"integer","minimum":0,"maximum":6,"default":0}}},"CatalogUnitPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogUnit"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogProduct":{"type":"object","additionalProperties":false,"required":["id","status","createdAt","updatedAt","name","slug","productType","categoryId","brandId","unitOfMeasure","publicationStatus","description","shortDescription"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":"string","maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500}}},"PublicCatalogProductPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogProduct"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogVariant":{"type":"object","additionalProperties":false,"required":["id","status","createdAt","updatedAt","modelNumber","barcode","storage","color","sku","condition","grade","simType","productId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"modelNumber":{"type":["string","null"],"maxLength":100},"barcode":{"type":["string","null"],"maxLength":100},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"sku":{"type":"string","maxLength":100,"pattern":"^[A-Z0-9][A-Z0-9_./-]{0,99}$"},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null]},"grade":{"enum":["A","B","C",null]},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"],"default":"NOT_APPLICABLE"},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogVariantPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogVariant"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogMedia":{"type":"object","additionalProperties":false,"required":["id","status","url","variantId","altText","position","productId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"url":{"type":"string","maxLength":2048,"format":"uri","description":"Unsigned HTTPS URL, no userinfo, query or fragment. Metadata only; API and worker never fetch it."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"altText":{"type":["string","null"],"maxLength":300},"position":{"type":"integer","minimum":0,"maximum":10000,"default":0},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogMediaPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogMedia"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogLookup":{"type":"object","additionalProperties":false,"required":["id","name","code"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":64,"pattern":"^[A-Z][A-Z0-9_.-]*$"}}},"PublicCatalogLookupPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogLookup"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogUnit":{"type":"object","additionalProperties":false,"required":["id","name","code","decimalPlaces"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string","maxLength":200,"minLength":1},"code":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"decimalPlaces":{"type":"integer","minimum":0,"maximum":6,"default":0}}},"PublicCatalogUnitPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogUnit"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"CatalogLookupUnionInput":{"description":"units accepts decimalPlaces 0..6 and a 16-character unit code; brands/categories/manufacturers accept name/code only.","anyOf":[{"$ref":"#/components/schemas/CatalogLookupInput"},{"$ref":"#/components/schemas/CatalogUnitInput"}]},"CatalogLookupUnion":{"anyOf":[{"$ref":"#/components/schemas/CatalogLookup"},{"$ref":"#/components/schemas/CatalogUnit"}]},"CatalogLookupUnionPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogLookupUnion"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"PublicCatalogLookupUnion":{"anyOf":[{"$ref":"#/components/schemas/PublicCatalogLookup"},{"$ref":"#/components/schemas/PublicCatalogUnit"}]},"PublicCatalogLookupUnionPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogLookupUnion"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"EmptyCatalogInput":{"type":"object","additionalProperties":false,"required":[],"properties":{}},"PriceListInput":{"type":"object","additionalProperties":false,"required":["code","name","currencyCode"],"properties":{"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64,"description":"Normalized uppercase; immutable and reserved after archive."},"name":{"type":"string","minLength":1,"maxLength":200},"currencyCode":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"description":{"type":["string","null"],"maxLength":2000},"visibility":{"enum":["INTERNAL","PUBLIC"],"default":"INTERNAL","description":"Explicit PUBLIC opt-in permits API-key pricing.read; INTERNAL remains private to human pricing.read and authorized pricing.write mutations."}}},"PriceInput":{"type":"object","additionalProperties":false,"required":["variantId","currencyCode","amount"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact non-negative decimal, up to 12 integer and 6 fractional digits. JSON numbers/exponents/excess scale rejected. Returned with exactly 6 fractional digits; no rounding or binary floating arithmetic.","examples":["0.000001","123.456789","999999999999.999999"]},"validFrom":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."},"validTo":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."}}},"PriceList":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","code","name","currencyCode","description","visibility"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64,"description":"Normalized uppercase; immutable and reserved after archive."},"name":{"type":"string","minLength":1,"maxLength":200},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"description":{"type":["string","null"],"maxLength":2000},"visibility":{"enum":["INTERNAL","PUBLIC"],"description":"Explicit PUBLIC opt-in permits API-key pricing.read; INTERNAL remains private to human pricing.read and authorized pricing.write mutations."}}},"Price":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","priceListId","variantId","currencyCode","amount","validFrom","validTo"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal, up to 12 integer and 6 fractional digits. JSON numbers/exponents/excess scale rejected. Returned with exactly 6 fractional digits; no rounding or binary floating arithmetic.","examples":["0.000001","123.456789","999999999999.999999"]},"validFrom":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."},"validTo":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."}}},"PublicPriceList":{"type":"object","additionalProperties":false,"required":["id","status","createdAt","updatedAt","code","name","currencyCode","visibility"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64,"description":"Normalized uppercase; immutable and reserved after archive."},"name":{"type":"string","minLength":1,"maxLength":200},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"visibility":{"enum":["INTERNAL","PUBLIC"],"description":"Explicit PUBLIC opt-in permits API-key pricing.read; INTERNAL remains private to human pricing.read and authorized pricing.write mutations."}}},"PublicPrice":{"type":"object","additionalProperties":false,"required":["id","status","createdAt","updatedAt","priceListId","variantId","currencyCode","amount","validFrom","validTo"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Price currency must match its list; no FX."},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal, up to 12 integer and 6 fractional digits. JSON numbers/exponents/excess scale rejected. Returned with exactly 6 fractional digits; no rounding or binary floating arithmetic.","examples":["0.000001","123.456789","999999999999.999999"]},"validFrom":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."},"validTo":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$","description":"Strict calendar-valid UTC year 0001..9999, at most 3 fractional second digits. Null is unbounded; validFrom inclusive and validTo exclusive; from must be strictly before to."}}},"PriceListPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PriceList"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"PricePage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/Price"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"PublicPriceListPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicPriceList"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"PublicPricePage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicPrice"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"EmptyPricingInput":{"type":"object","additionalProperties":false,"required":[],"properties":{}},"WarehouseInput":{"type":"object","additionalProperties":false,"required":["code","name","type","legalEntityId"],"properties":{"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"enum":["PHYSICAL","VIRTUAL","IN_TRANSIT","THIRD_PARTY","QUARANTINE"]},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"branchId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}},"description":"PHYSICAL requires a non-null branch within the same tenant/legal entity. All five types require legalEntityId; special types may omit branch. Code/type/hierarchy immutable."},"Warehouse":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","code","name","type","legalEntityId","branchId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"enum":["PHYSICAL","VIRTUAL","IN_TRANSIT","THIRD_PARTY","QUARANTINE"]},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"branchId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"WarehouseLocationInput":{"type":"object","additionalProperties":false,"required":["code","name"],"properties":{"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200}}},"WarehouseLocation":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","warehouseId","code","name"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]*$","maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200}}},"InventoryAdjustmentInput":{"type":"object","additionalProperties":false,"required":["variantId","movementType","quantity","reason"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Positive exact decimal string, max 12 integer and 6 fractional digits, further limited to the variant unit decimalPlaces. Numbers, exponent, zero, negative, excess scale rejected; no implicit rounding."},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"movementType":{"enum":["ADJUSTMENT_IN","ADJUSTMENT_OUT","DAMAGE","LOSS"]},"fromWarehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"toWarehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"unitCost":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"ADJUSTMENT_IN only. Unit cost of the stock that enters. Required when the legal entity keeps books (409 VALUATION_COST_REQUIRED otherwise): a cost is never assumed, not even zero."}},"description":"ADJUSTMENT_IN: only toWarehouseId. Other enabled adjustment types: only fromWarehouseId. Tracked GOOD without serials; active product for inbound; outflow may drain archived product. Reason is mandatory. Reference type MANUAL assigned by server; purchase/sale/RMA types unavailable."},"InventoryTransferInput":{"type":"object","additionalProperties":false,"required":["variantId","fromWarehouseId","toWarehouseId","quantity","reason"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Positive exact decimal string, max 12 integer and 6 fractional digits, further limited to the variant unit decimalPlaces. Numbers, exponent, zero, negative, excess scale rejected; no implicit rounding."},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"movementType":{"enum":["TRANSFER"]},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"description":"Distinct active warehouses in the same tenant and legal entity. Atomic debit/credit; reserved stock cannot be transferred; no shipment workflow."},"InventoryMovementReceipt":{"type":"object","additionalProperties":false,"required":["id","variantId","movementType","quantity","createdAt"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"movementType":{"enum":["ADJUSTMENT_IN","ADJUSTMENT_OUT","TRANSFER","DAMAGE","LOSS","PURCHASE_RECEIPT","SALE"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"createdAt":{"type":"string","format":"date-time"}}},"InventoryMovement":{"type":"object","additionalProperties":false,"required":["id","variantId","movementType","quantity","createdAt","tenantId","fromWarehouseId","toWarehouseId","reason","referenceType","referenceId","actorType","actorId","requestId","inventoryUnitId","unitVersion","fromLocationId","toLocationId","fromStatus","toStatus","purchaseReceiptItemId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"movementType":{"enum":["ADJUSTMENT_IN","ADJUSTMENT_OUT","TRANSFER","DAMAGE","LOSS","PURCHASE_RECEIPT","SALE"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"createdAt":{"type":"string","format":"date-time"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromWarehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"toWarehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceType":{"type":"string","enum":["MANUAL","GOODS_RECEIPT","SALES_ORDER"]},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"actorType":{"enum":["USER","API_CLIENT"]},"actorId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"unitVersion":{"type":["integer","null"],"minimum":1},"fromLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"toLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"fromStatus":{"anyOf":[{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},{"type":"null"}]},"toStatus":{"anyOf":[{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},{"type":"null"}]},"purchaseReceiptItemId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"saleAllocationId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"InventoryReservationInput":{"type":"object","additionalProperties":false,"required":["variantId","warehouseId","quantity","reason"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Positive exact decimal string, max 12 integer and 6 fractional digits, further limited to the variant unit decimalPlaces. Numbers, exponent, zero, negative, excess scale rejected; no implicit rounding."},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"description":"Manual explicit hold in active PHYSICAL/VIRTUAL/THIRD_PARTY warehouse; positive exact available quantity. No expiration, sale allocation or consumption in INV-1."},"InventoryReservationReceipt":{"type":"object","additionalProperties":false,"required":["id","variantId","quantity","status","createdAt","releasedAt"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"status":{"enum":["ACTIVE","RELEASED","CONSUMED"]},"createdAt":{"type":"string","format":"date-time"},"releasedAt":{"type":["string","null"],"format":"date-time"},"inventoryUnitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"InventoryReservation":{"type":"object","additionalProperties":false,"required":["id","variantId","quantity","status","createdAt","releasedAt","tenantId","warehouseId","reason","referenceType","referenceId","actorType","actorId","requestId","inventoryUnitId","warehouseLocationId","expectedUnitVersion"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"status":{"enum":["ACTIVE","RELEASED","CONSUMED"]},"createdAt":{"type":"string","format":"date-time"},"releasedAt":{"type":["string","null"],"format":"date-time"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceType":{"enum":["MANUAL","SALES_ORDER"]},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"actorType":{"enum":["USER","API_CLIENT"]},"actorId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"warehouseLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"expectedUnitVersion":{"type":["integer","null"],"minimum":1},"salesOrderItemId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"InventoryStock":{"type":"object","additionalProperties":false,"required":["warehouseId","variantId","onHand","reserved","available"],"properties":{"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"onHand":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"reserved":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"available":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"updatedAt":{"type":"string","format":"date-time"}},"description":"Read-only projection from movements and separate reservation events; available=onHand-reserved. Missing pair returns zero balances without creating a stock row; no incoming field."},"InventoryReconciliation":{"type":"object","additionalProperties":false,"required":["warehouseId","variantId","expectedOnHand","expectedReserved","onHand","reserved","matches"],"properties":{"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"expectedOnHand":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"expectedReserved":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"onHand":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"reserved":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Exact non-negative decimal string with six fractional digits; zero is permitted in stock balances."},"matches":{"type":"boolean"}}},"InventoryAvailability":{"type":"object","additionalProperties":false,"required":["variantId","status"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["IN_STOCK","OUT_OF_STOCK"]}},"description":"API-key summary for active published tracked GOOD; quantity variants use onHand-reserved, serialized variants count AVAILABLE units. Active PHYSICAL/VIRTUAL/THIRD_PARTY only; excludes QUARANTINE/IN_TRANSIT, RESERVED/DAMAGED/LOST. No identifiers, quantities, warehouses/locations or costs."},"EmptyInventoryInput":{"type":"object","additionalProperties":false,"required":[],"properties":{}},"WarehousePage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/Warehouse"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"WarehouseLocationPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/WarehouseLocation"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"InventoryStockPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/InventoryStock"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"InventoryMovementPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/InventoryMovement"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"InventoryReservationPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/InventoryReservation"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"InventoryUnitInput":{"type":"object","additionalProperties":false,"required":["variantId","warehouseId","reason"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","maxLength":100},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"Condition of the unit. Optional when its SKU states one, which is then taken; required when the SKU states none (409 UNIT_CONDITION_REQUIRED). Never assumed to be NEW. A value other than the one the SKU states is refused with 409 UNIT_CONDITION_MISMATCH."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"Grade of the unit. Optional: the SKU proposes its own, and a unit of a SKU that states none may have one or not. A value other than the one the SKU states is refused with 409 UNIT_CONDITION_MISMATCH."},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"unitCost":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Cost of a unit registered by hand. Required when the legal entity keeps books. A unit received from a purchase takes the cost of its order line."}},"description":"Register one tracked serialized GOOD plus initial ADJUSTMENT_IN in one transaction. At least one serial/IMEI required. Serial uppercased/trimmed, IMEI unique across both slots within tenant; IDs permanent. Condition defaults NEW, grade null. Legal entity derived from destination; identities/condition/grade immutable. Cost/quantity/status/actor/tenant inputs rejected."},"InventoryUnitReceipt":{"type":"object","additionalProperties":false,"required":["id","variantId","status","version","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"description":"Write receipt always omits serials/IMEI, warehouse/location, legal entity, actor and costs; permission to write never implies permission to read identifiers."},"ApiInventoryUnit":{"type":"object","additionalProperties":false,"required":["id","variantId","status","version","createdAt","updatedAt","serialNumber","imei1","imei2","condition","grade"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","maxLength":100},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS"]},"grade":{"type":["string","null"],"enum":["A","B","C",null]}},"description":"Dedicated operational read requiring both inventory.read and inventory.serials.read plus PUBLIC_API; no warehouse/location, legal entity, actor, current reservation or costs. Units need not be published because this is explicit private serial access, separate from public availability."},"InventoryUnit":{"type":"object","additionalProperties":false,"required":["id","variantId","status","version","createdAt","updatedAt","serialNumber","imei1","imei2","condition","grade","tenantId","legalEntityId","warehouseId","warehouseLocationId","activeReservationId","actorType","actorId","requestId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","maxLength":100},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS"]},"grade":{"type":["string","null"],"enum":["A","B","C",null]},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"warehouseLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"activeReservationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"actorType":{"enum":["USER","API_CLIENT"]},"actorId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"InventoryUnitMovementInput":{"type":"object","additionalProperties":false,"required":["movementType","expectedVersion","reason"],"properties":{"movementType":{"enum":["ADJUSTMENT_IN","TRANSFER","DAMAGE","LOSS"]},"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646},"toWarehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"toLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"unitCost":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"ADJUSTMENT_IN only: cost at which a lost unit re-enters the books. Required when the legal entity keeps books."}},"description":"Fixed quantity 1. Transfer/ADJUSTMENT_IN requires destination; toLocation optional. DAMAGE/LOSS reject destination inputs. Stale version or reserved unit gives 409. Initial receipt is registration; ADJUSTMENT_IN here only readmits LOST. Transfers preserve legal entity, may move between locations of one warehouse, derive IN_TRANSIT/QUARANTINED/AVAILABLE from warehouse type and preserve DAMAGED. DAMAGE retains current custody; LOSS clears warehouse/location. No direct status, quantity or identity patch; SALE/returns/RMA unavailable."},"InventoryUnitReservationInput":{"type":"object","additionalProperties":false,"required":["expectedVersion","reason"],"properties":{"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646},"reason":{"type":"string","minLength":1,"maxLength":1000},"referenceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}},"description":"Reserve exactly one AVAILABLE unit in active normal warehouse. Source reservation/events shared with INV-1, without quantity stock. Release via existing reservations/{id}/release; entire hold once, no expiry/consumption."},"InventoryUnitReservationReceipt":{"type":"object","additionalProperties":false,"required":["id","inventoryUnitId","variantId","quantity","status","unitVersion"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"const":"1.000000"},"status":{"const":"ACTIVE"},"unitVersion":{"type":"integer","minimum":1,"maximum":2147483646}}},"InventoryUnitReconciliation":{"type":"object","additionalProperties":false,"required":["inventoryUnitId","matches","eventCount","actual","expected"],"properties":{"inventoryUnitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"matches":{"type":"boolean"},"eventCount":{"type":"string","pattern":"^[0-9]+$"},"actual":{"type":"object","additionalProperties":false,"required":["warehouseId","warehouseLocationId","status","activeReservationId","version"],"properties":{"warehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"warehouseLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"activeReservationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"version":{"type":"integer","minimum":1,"maximum":2147483646}}},"expected":{"type":"object","additionalProperties":false,"required":["warehouseId","warehouseLocationId","status","activeReservationId","version"],"properties":{"warehouseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"warehouseLocationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"activeReservationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]},"version":{"type":"integer","minimum":1,"maximum":2147483646}}}}},"InventoryUnitSummary":{"type":"object","additionalProperties":false,"required":["warehouseId","items"],"properties":{"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"items":{"type":"array","maxItems":9,"items":{"type":"object","additionalProperties":false,"required":["variantId","status","count"],"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"count":{"type":"string","pattern":"^[0-9]+$"}}}}}},"InventoryUnitPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/InventoryUnit"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"ApiInventoryUnitPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ApiInventoryUnit"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}]}}},"SearchVariant":{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"VARIANT"},"id":{"type":"string","format":"uuid"},"variantId":{"type":"string","format":"uuid"},"productId":{"type":"string","format":"uuid"},"productName":{"type":"string"},"sku":{"type":"string"},"match":{"type":"string","enum":["EXACT_IMEI","EXACT_SKU","EXACT_BARCODE","EXACT_SERIAL","EXACT_MODEL","TEXT","TRIGRAM"]},"modelNumber":{"type":["string","null"],"maxLength":100},"barcode":{"type":["string","null"],"maxLength":100},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null]},"grade":{"enum":["A","B","C",null]},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"],"default":"NOT_APPLICABLE"}},"required":["kind","id","variantId","productId","productName","sku","match","modelNumber","barcode","storage","color","condition","grade","simType"]},"SearchUnit":{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"INVENTORY_UNIT"},"id":{"type":"string","format":"uuid"},"variantId":{"type":"string","format":"uuid"},"productId":{"type":"string","format":"uuid"},"productName":{"type":"string"},"sku":{"type":"string"},"match":{"type":"string","enum":["EXACT_IMEI","EXACT_SKU","EXACT_BARCODE","EXACT_SERIAL","EXACT_MODEL","TEXT","TRIGRAM"]},"modelNumber":{"type":["string","null"],"maxLength":100},"barcode":{"type":["string","null"],"maxLength":100},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null]},"grade":{"enum":["A","B","C",null]},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"],"default":"NOT_APPLICABLE"},"unitStatus":{"type":"string","enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"unitVersion":{"type":"integer","minimum":1}},"required":["kind","id","variantId","productId","productName","sku","match","modelNumber","barcode","storage","color","condition","grade","simType","unitStatus","unitVersion"]},"SearchPage":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"oneOf":[{"$ref":"#/components/schemas/SearchVariant"},{"$ref":"#/components/schemas/SearchUnit"}],"discriminator":{"propertyName":"kind"}}},"nextCursor":{"type":["string","null"],"maxLength":600,"description":"Opaque cursor bound to normalized input, tenant/principal, archive visibility and current serial capability; fresh state may change results between pages."}}},"SupplierInput":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":["string","null"],"maxLength":64},"email":{"type":["string","null"],"maxLength":254},"phone":{"type":["string","null"],"maxLength":64},"address":{"type":["string","null"],"maxLength":1000,"description":"Free text of up to 1000 characters. May hold several lines (CRLF is stored as LF); any other control character is refused."},"profile":{"$ref":"#/components/schemas/ContactProfileInput"}},"required":["code","name"]},"SupplierReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","createdAt","updatedAt"]},"Supplier":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":["string","null"],"maxLength":64},"email":{"type":["string","null"],"maxLength":254},"phone":{"type":["string","null"],"maxLength":64},"address":{"type":["string","null"],"maxLength":1000,"description":"Free text of up to 1000 characters. May hold several lines (CRLF is stored as LF); any other control character is refused."},"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"profile":{"$ref":"#/components/schemas/ContactProfile"}},"required":["code","name","taxId","email","phone","address","id","status","createdAt","updatedAt","profile"]},"PurchaseItemInput":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$"},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$"}},"required":["variantId","quantity","unitCost"]},"PurchaseOrderInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[a-zA-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseItemInput"},"maxItems":100,"minItems":1}},"required":["number","legalEntityId","warehouseId","supplierId","currencyCode","items"]},"PurchaseOrderUpdate":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[a-zA-Z]{3}$","description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseItemInput"},"maxItems":100,"minItems":1},"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646}},"required":["number","legalEntityId","warehouseId","supplierId","currencyCode","items","expectedVersion"]},"PurchaseVersionInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646}},"required":["expectedVersion"]},"PurchaseOrderReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","version","createdAt","updatedAt"]},"PurchaseOrderHeader":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000}},"required":["id","status","version","createdAt","updatedAt","number","supplierId","currencyCode","legalEntityId","warehouseId","notes"]},"ApiPurchaseOrderHeader":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."}},"required":["id","status","version","createdAt","updatedAt","number","supplierId","currencyCode"]},"PurchaseOrderItem":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"receivedQuantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"trackingMode":{"type":"string","enum":["NONE","QUANTITY","SERIALIZED"]},"lineTotal":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"}},"required":["id","variantId","quantity","unitCost","receivedQuantity","trackingMode","lineTotal"]},"PurchaseOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrderItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"}},"required":["id","status","version","createdAt","updatedAt","number","supplierId","currencyCode","legalEntityId","warehouseId","notes","items","total"]},"ApiPurchaseOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","APPROVED","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrderItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"}},"required":["id","status","version","createdAt","updatedAt","number","supplierId","currencyCode","items","total"]},"ReceiptUnitInput":{"type":"object","additionalProperties":false,"properties":{"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","maxLength":100},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with Luhn check digit; all-zero placeholder rejected. Not IMEISV and no authenticity/TAC verification."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"Condition of the unit. Optional when its SKU states one, which is then taken; required when the SKU states none (409 UNIT_CONDITION_REQUIRED). Never assumed to be NEW. A value other than the one the SKU states is refused with 409 UNIT_CONDITION_MISMATCH."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"Grade of the unit. Optional: the SKU proposes its own, and a unit of a SKU that states none may have one or not. A value other than the one the SKU states is refused with 409 UNIT_CONDITION_MISMATCH."}},"required":[],"anyOf":[{"required":["serialNumber"],"properties":{"serialNumber":{"type":"string","minLength":1}}},{"required":["imei1"],"properties":{"imei1":{"type":"string","minLength":1}}},{"required":["imei2"],"properties":{"imei2":{"type":"string","minLength":1}}}],"description":"At least one serial/IMEI identity is required. Strings are normalized as INV-2; IMEIs require Luhn. Only new units can be received; duplicates abort the entire receipt."},"ReceiptItemInput":{"type":"object","additionalProperties":false,"properties":{"orderItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$"},"units":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptUnitInput"},"maxItems":100}},"required":["orderItemId","quantity"]},"GoodsReceiptInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646},"reason":{"type":"string","minLength":1,"maxLength":1000},"warehouseLocationId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptItemInput"},"maxItems":100,"minItems":1}},"required":["expectedVersion","reason","items"],"description":"Only approved/open orders. Quantity cannot exceed outstanding quantity. SERIALIZED lines require matching units; at most 100 units total per receipt. QUANTITY/NONE reject units. All receipt and Inventory effects commit atomically."},"GoodsReceiptWrite":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderVersion":{"type":"integer","minimum":2},"createdAt":{"type":"string","format":"date-time"}},"required":["id","orderId","orderVersion","createdAt"]},"GoodsReceiptItem":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"trackingMode":{"type":"string","enum":["NONE","QUANTITY","SERIALIZED"]},"lineTotal":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"}},"required":["id","orderItemId","variantId","quantity","unitCost","trackingMode","lineTotal"]},"ApiGoodsReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderVersion":{"type":"integer","minimum":2},"createdAt":{"type":"string","format":"date-time"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"items":{"type":"array","items":{"$ref":"#/components/schemas/GoodsReceiptItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"}},"required":["id","orderId","orderVersion","createdAt","currencyCode","items","total"]},"GoodsReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderVersion":{"type":"integer","minimum":2},"createdAt":{"type":"string","format":"date-time"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"ISO currency supported by pinned Node ICU, normalized uppercase. Fixed on approval; no FX or accounting valuation."},"items":{"type":"array","items":{"$ref":"#/components/schemas/GoodsReceiptItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseLocationId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reason":{"type":"string","minLength":1,"maxLength":1000}},"required":["id","orderId","orderVersion","createdAt","currencyCode","items","total","warehouseId","warehouseLocationId","reason"]},"PurchaseIncoming":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"}},"required":["id","orderId","variantId","warehouseId","quantity"]},"ApiPurchaseIncoming":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"}},"required":["id","orderId","variantId","quantity"]},"SupplierPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Supplier"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"PurchaseOrderHeaderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrderHeader"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ApiPurchaseOrderHeaderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiPurchaseOrderHeader"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"GoodsReceiptWritePage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/GoodsReceiptWrite"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"PurchaseIncomingPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseIncoming"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ApiPurchaseIncomingPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiPurchaseIncoming"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"EmptyCommand":{"type":"object","additionalProperties":false,"properties":{},"required":[]},"CustomerInput":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":["string","null"],"maxLength":64},"email":{"type":["string","null"],"maxLength":254},"phone":{"type":["string","null"],"maxLength":64},"address":{"type":["string","null"],"maxLength":1000,"description":"Free text of up to 1000 characters. May hold several lines (CRLF is stored as LF); any other control character is refused."},"profile":{"$ref":"#/components/schemas/ContactProfileInput"}},"required":["code","name"]},"CustomerReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","createdAt","updatedAt"]},"Customer":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":["string","null"],"maxLength":64},"email":{"type":["string","null"],"maxLength":254},"phone":{"type":["string","null"],"maxLength":64},"address":{"type":["string","null"],"maxLength":1000,"description":"Free text of up to 1000 characters. May hold several lines (CRLF is stored as LF); any other control character is refused."},"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"profile":{"$ref":"#/components/schemas/ContactProfile"}},"required":["code","name","taxId","email","phone","address","id","status","createdAt","updatedAt","profile"]},"SalesItemInput":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$"},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Agreed price of one unit, when it is not the list price. Human users only. Not together with discountPercent. Equal to the list price, the line is simply priced by the list. Any other value needs sales.price.override (403 PRICE_OVERRIDE_DENIED) and priceReason (400 PRICE_REASON_REQUIRED)."},"discountPercent":{"type":"string","pattern":"^(100(\\.0{1,4})?|[0-9]{1,2}(\\.[0-9]{1,4})?)$","description":"Discount on the list price in force, above 0 and up to 100, with at most four decimals. Human users only. Not together with unitPrice: the service applies it once and stores the resulting agreed price. A result that needs more than six decimals is refused (409 PRICE_DISCOUNT_NOT_EXACT), never rounded. Needs sales.price.override and priceReason."},"priceReason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the price is not the list price. Only with unitPrice or discountPercent."}},"required":["variantId","quantity"]},"SalesOrderInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/SalesItemInput"},"maxItems":100,"minItems":1},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["number","legalEntityId","warehouseId","customerId","items","priceListId"]},"SalesOrderUpdate":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z][a-zA-Z0-9_.-]*$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/SalesItemInput"},"maxItems":100,"minItems":1},"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["number","legalEntityId","warehouseId","customerId","items","expectedVersion","priceListId"]},"SalesVersionInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646}},"required":["expectedVersion"]},"SalesOrderReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","version","createdAt","updatedAt"]},"SalesOrderHeader":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"Price-list currency, frozen on confirmation. No FX or fiscal rounding."},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","status","version","createdAt","updatedAt","number","customerId","currencyCode","legalEntityId","warehouseId","notes","priceListId"]},"ApiSalesOrderHeader":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"Price-list currency, frozen on confirmation. No FX or fiscal rounding."},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","status","version","createdAt","updatedAt","number","customerId","currencyCode","priceListId"]},"SalesOrderItem":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"trackingMode":{"type":"string","enum":["NONE","QUANTITY","SERIALIZED"]},"lineTotal":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"},"priceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"allocations":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/SalesAllocation"}},"listUnitPrice":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Reference: the list price the line was settled against. For a negotiated line it is a snapshot and does not follow the list. Null on an invoice line that has no list reference."},"priceNegotiated":{"type":"boolean","description":"True when the agreed unit price is not the list price. Such a line keeps its price through confirmation, delivery, invoicing and collection."},"discountPercent":{"type":["string","null"],"pattern":"^(100|[0-9]{1,2})\\.[0-9]{4}$","description":"The discount the price was stated as, when it was stated as one."},"discountAmount":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"What one unit is discounted by: list price minus agreed price. Null when the agreed price is not below the list price."},"priceReason":{"type":["string","null"],"maxLength":500},"priceOrigin":{"enum":["QUOTATION","SALES_ORDER","SALES_INVOICE",null],"type":["string","null"],"description":"The document the price was negotiated in. A line carried to another document keeps it."},"units":{"type":"array","maxItems":100,"description":"Only on the record read by a person: the units this line reserved or delivered, read from the allocations of the order itself. Identifiers and state are sent only on the record of the document and only to a reader of inventory.serials.read; everyone else receives the unit references and their count.","items":{"type":"object","additionalProperties":false,"properties":{"unitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"outcome":{"enum":["RESERVED","DELIVERED","RELEASED"],"description":"RESERVED: held by the confirmed order. DELIVERED: it left with the sale. RELEASED: the order was cancelled and let it go."},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"],"description":"State of the unit today, wherever it is now."}},"required":["unitId","outcome"]}}},"required":["id","variantId","quantity","trackingMode","lineTotal","priceId","unitPrice","allocations"]},"SalesOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"Price-list currency, frozen on confirmation. No FX or fiscal rounding."},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrderItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitIdentifiers":{"type":"boolean","description":"Only on the record: whether this reader received the identifiers of the units (inventory.serials.read)."}},"required":["id","status","version","createdAt","updatedAt","number","customerId","currencyCode","legalEntityId","warehouseId","notes","items","total","priceListId"]},"ApiSalesOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string","enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"version":{"type":"integer","minimum":1,"maximum":2147483646},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string","minLength":1,"maxLength":64},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","minLength":1,"maxLength":3,"description":"Price-list currency, frozen on confirmation. No FX or fiscal rounding."},"items":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrderItem"},"maxItems":100},"total":{"type":"string","pattern":"^[0-9]{1,26}\\.[0-9]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","status","version","createdAt","updatedAt","number","customerId","currencyCode","items","total","priceListId"]},"CustomerPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Customer"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"SalesOrderHeaderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrder"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ApiSalesOrderHeaderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiSalesOrder"},"maxItems":100},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"SalesConfirmInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1,"maximum":2147483646},"units":{"type":"array","maxItems":100,"description":"Only serialized lines; at most 100 units total. All quantities must be covered exactly. UUIDs only, no serial/IMEI data.","items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitIds":{"type":"array","minItems":1,"maxItems":100,"uniqueItems":true,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","unitIds"]}}},"required":["expectedVersion"]},"SalesAllocation":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reservationId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"movementId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","reservationId","quantity","movementId"]},"PosRegisterInput":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","maxLength":64},"name":{"type":"string","maxLength":200},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"branchId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"cashScale":{"type":"integer","minimum":0,"maximum":6,"default":2}},"required":["code","name","legalEntityId","branchId","warehouseId","priceListId"]},"PosRegister":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","maxLength":64},"name":{"type":"string","maxLength":200},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"branchId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"cashScale":{"type":"integer","minimum":0,"maximum":6,"default":2},"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["code","name","legalEntityId","branchId","warehouseId","priceListId","cashScale","id","tenantId","currencyCode","status","createdAt","updatedAt"]},"PosOpenInput":{"type":"object","additionalProperties":false,"properties":{"registerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"openingAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."}},"required":["registerId","openingAmount"]},"PosCloseInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"countedAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."}},"required":["expectedVersion","countedAmount"]},"PosCheckoutInput":{"type":"object","additionalProperties":false,"properties":{"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"expectedOrderVersion":{"type":"integer","minimum":1},"expectedSessionVersion":{"type":"integer","minimum":1},"tenderedAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Historical form: the whole sale in cash and the cash handed over. Mutually exclusive with `payments`."},"payments":{"type":"array","minItems":1,"maxItems":8,"description":"Payment components. Their amounts add up to the order total exactly; at most one is CASH. Mutually exclusive with `tenderedAmount`.","items":{"$ref":"#/components/schemas/PaymentComponentInput"}},"cashTendered":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Cash handed over for the CASH component; defaults to its amount. The excess is the change. Refused without a CASH component: a card or a transfer never finances change."}},"required":["orderId","expectedOrderVersion","expectedSessionVersion"]},"PosSession":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"registerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"operatorId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["OPEN","CLOSED"]},"version":{"type":"integer","minimum":1},"openingAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."},"expectedAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."},"countedAmount":{"type":["string","null"]},"variance":{"type":["string","null"],"description":"Signed countedAmount minus expectedAmount; closed snapshot."},"closedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"collected":{"type":"object","additionalProperties":false,"properties":{"CASH":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"TRANSFER":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"CARD":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"CHECK":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"OTHER":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["CASH","TRANSFER","CARD","CHECK","OTHER"],"description":"Collected in the session with each method. Only cash counts for `expectedAmount`: cards and transfers are shown apart."},"cashIn":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Cash that entered the till outside a sale."},"cashOut":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Cash that left the till outside a sale."}},"required":["id","tenantId","registerId","operatorId","status","version","openingAmount","expectedAmount","countedAmount","variance","closedAt","createdAt","updatedAt","collected","cashIn","cashOut"]},"PosReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionVersion":{"type":"integer","minimum":1},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"total":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."},"tenderedAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."},"changeAmount":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact nonnegative cash amount. At most12 integer digits and6 decimals; precision must be representable under register cashScale. No rounding or FX."},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"},"cashAmount":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Cash that stayed in the till. Null on receipts older than payment components, which were cash in full."},"payments":{"type":"array","description":"Present on checkout and when a receipt is read by id.","items":{"$ref":"#/components/schemas/PosReceiptPayment"}}},"required":["id","tenantId","sessionId","sessionVersion","orderId","currencyCode","total","tenderedAmount","changeAmount","requestId","createdAt","cashAmount"]},"PosRegisterPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PosRegister"}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["items","nextCursor"]},"PosSessionPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PosSession"}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["items","nextCursor"]},"PosReceiptPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PosReceipt"}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["items","nextCursor"]},"PosEmpty":{"type":"object","additionalProperties":false,"properties":{},"required":[]},"Workspace":{"type":"object","additionalProperties":false,"required":["tenant","legalEntities","branches"],"properties":{"tenant":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"legalEntities":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}},"branches":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","legalEntityId"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid"}}}}}},"CatalogVariantReference":{"type":"object","additionalProperties":false,"description":"How a variant is named wherever it is referred to: its SKU, the general name of its product and what tells its versions apart. The same fields a search result carries, so a selection read back by id is named as when it was chosen. No costs, suppliers, attributes or serials.","required":["id","productId","sku","productName","storage","color","simType","trackingMode","condition","grade"],"properties":{"id":{"type":"string","format":"uuid"},"productId":{"type":"string","format":"uuid"},"sku":{"type":"string"},"productName":{"type":"string"},"storage":{"type":["string","null"],"maxLength":100},"color":{"type":["string","null"],"maxLength":100},"simType":{"enum":["ESIM","PHYSICAL_SIM","PHYSICAL_ESIM","DUAL_SIM","NOT_APPLICABLE"]},"trackingMode":{"enum":["SERIALIZED","QUANTITY","NONE"],"description":"How the stock of the article is kept. Only a SERIALIZED article has physical units with IMEI or serial number."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"What the SKU says its units are: the condition a new unit is proposed with. Null when the SKU states none and each unit says its own."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"The grade the SKU states for its units, when it states one."}}},"ImportOrderInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"fromLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Another legal entity of the same tenant."},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitOwner":{"enum":["ORIGIN","DESTINATION"],"description":"Which legal entity owns the goods while they travel. The transit warehouse must belong to it."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"originDocument":{"type":["string","null"],"maxLength":200},"destinationDocument":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Declared value per unit in the order currency. Not a cost or a price."}},"required":["variantId","quantity","unitValue"]}}},"required":["number","fromLegalEntityId","toLegalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","transitOwner","currencyCode","items"]},"ImportOrderUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"fromLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Another legal entity of the same tenant."},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitOwner":{"enum":["ORIGIN","DESTINATION"],"description":"Which legal entity owns the goods while they travel. The transit warehouse must belong to it."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"originDocument":{"type":["string","null"],"maxLength":200},"destinationDocument":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Declared value per unit in the order currency. Not a cost or a price."}},"required":["variantId","quantity","unitValue"]}},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","fromLegalEntityId","toLegalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","transitOwner","currencyCode","items","expectedVersion"]},"ImportDispatchInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"originDocument":{"type":["string","null"],"maxLength":200},"units":{"type":"array","maxItems":100,"description":"Exact units leaving for every serialized line; quantity lines take none.","items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","unitIds"]}}},"required":["expectedVersion"]},"ImportReceiptInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"destinationDocument":{"type":["string","null"],"maxLength":200},"reason":{"type":["string","null"],"maxLength":1000,"description":"Required when any line is LOST or RETURNED."},"lines":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"outcome":{"enum":["RECEIVED","LOST","RETURNED"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","outcome"]}}},"required":["expectedVersion","lines"]},"ImportOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"fromLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Owner of the goods in transit."},"transitOwner":{"enum":["ORIGIN","DESTINATION"],"description":"Which legal entity owns the goods while they travel. The transit warehouse must belong to it."},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"originDocument":{"type":["string","null"]},"destinationDocument":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":2000},"declaredValue":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"lineValue":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."},"trackingMode":{"enum":["QUANTITY","SERIALIZED"]},"dispatched":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"received":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"lost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"returned":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"inTransit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"units":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"unitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"outcome":{"enum":["IN_TRANSIT","RECEIVED","LOST","RETURNED"],"description":"What became of the unit this order dispatched."},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"],"description":"State of the unit today, wherever it is now."}},"required":["unitId","outcome"],"description":"A unit this order dispatched, by its own movements: it stays here after it is sold or moved again. Identifiers and state are sent only on the record of the document and only to a reader of inventory.serials.read; everyone else receives the unit references and their count."}}},"required":["id","variantId","quantity","unitValue","lineValue","trackingMode","dispatched","received","lost","returned","inTransit","units"]}},"movements":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"kind":{"enum":["DISPATCH","RECEIVED","LOST","RETURNED"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"movementId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","itemId","kind","quantity","inventoryUnitId","movementId","createdAt"]}},"unitIdentifiers":{"type":"boolean","description":"Only on the record: whether this reader received the identifiers of the units (inventory.serials.read)."}},"required":["id","status","version","createdAt","updatedAt","number","fromLegalEntityId","toLegalEntityId","transitLegalEntityId","transitOwner","fromWarehouseId","toWarehouseId","transitWarehouseId","currencyCode","originDocument","destinationDocument","notes","declaredValue","items","movements"]},"ImportOrderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ImportOrder"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"StockReportRow":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","description":"Opaque row key; also the cursor."},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityName":{"type":"string"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseName":{"type":"string"},"warehouseType":{"type":"string"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productName":{"type":"string"},"sku":{"type":"string"},"onHand":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"reserved":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"available":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."}},"required":["id","legalEntityId","legalEntityName","warehouseId","warehouseName","warehouseType","variantId","productName","sku","onHand","reserved","available"]},"StockReportPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StockReportRow"}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"]},"TransitReportRow":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"kind":{"enum":["TRANSFER","IMPORT"]},"orderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderNumber":{"type":"string"},"orderStatus":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productName":{"type":"string"},"sku":{"type":"string"},"ownerLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Entity that owns the goods while in transit."},"ownerLegalEntityName":{"type":"string"},"fromLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toLegalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inTransit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"currencyCode":{"type":["string","null"]},"declaredValue":{"type":["string","null"],"description":"Declared value of what is still in transit; imports only."}},"required":["id","kind","orderId","orderNumber","orderStatus","variantId","productName","sku","ownerLegalEntityId","ownerLegalEntityName","fromLegalEntityId","toLegalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","inTransit","currencyCode","declaredValue"]},"TransitReportPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TransitReportRow"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"BalanceReportRow":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyName":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityName":{"type":"string"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"openInvoices":{"type":"integer","minimum":0},"balance":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Sum of the balances of issued invoices."},"available":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Recognised credits not yet applied or refunded."},"unapplied":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Recorded payments not yet applied."}},"required":["id","partyName","legalEntityId","legalEntityName","currencyCode","openInvoices","balance","available","unapplied"]},"BalanceReportPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BalanceReportRow"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"InvoiceInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer for sales documents, supplier for purchase documents."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"issueDate":{"type":"string","format":"date","description":"Calendar day."},"dueDate":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"notes":{"type":["string","null"],"maxLength":2000},"warehouseId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Active warehouse of the legal entity where the goods of a direct purchase arrive or those of a direct sale leave. Omitted for an invoice of an order: the order has its own."},"priceListId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Sales invoices without an order: the list a direct sale is priced by; saving one needs pricing.read. Each line with an article the list prices is the list price or an agreed price recorded with authorization, and its delivery carries those prices to the order it writes."},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string","maxLength":500},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Price of one unit. Required unless the line states discountPercent. On a sales invoice that names a price list, for an article the list prices: a value other than the list price is an agreed price and needs sales.price.override (403 PRICE_OVERRIDE_DENIED) and priceReason (400 PRICE_REASON_REQUIRED); the same value the draft already had agreed, with the same quantity, is kept without deciding again."},"discountPercent":{"type":"string","pattern":"^(100(\\.0{1,4})?|[0-9]{1,2}(\\.[0-9]{1,4})?)$","description":"Sales invoices that name a price list, on a line with an article: a discount on the list price in force, instead of unitPrice and never with it. The service applies it once and stores the agreed unit price; a result with more than six decimals is refused (409 PRICE_DISCOUNT_NOT_EXACT). Needs sales.price.override and priceReason."},"priceReason":{"type":"string","minLength":1,"maxLength":500,"description":"Sales invoices that name a price list, on a line with an article: why its price is not the list price."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Article of the line. Saving an invoice moves no inventory."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Unit (IMEI) reference only."},"devices":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","description":"Stored in capitals."},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with a valid check digit."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"Second IMEI of the same phone: one unit, never two. Different from imei1."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"Condition the unit will be received with. Its SKU proposes it: left out, the one the SKU states is saved; where the SKU states none it must be given (409 UNIT_CONDITION_REQUIRED), because nothing is assumed to be new. A value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH). Read back: null only for a device saved before conditions were asked."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"Grade of the unit, optional. The SKU proposes its own; a value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH)."}},"required":[]},"description":"Supplier bills without a purchase order: the devices of a serialized line, typed by their identifiers. They are not units until the bill is confirmed with its receipt. At most as many as the line bills, 100 in the invoice, and no identifier twice."},"unitIds":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Units that exist. On a supplier bill with a purchase order: units that order received and no other bill names. On a sales invoice without an order: units of the article, available in the invoice warehouse, that the direct sale will deliver. Saving them reserves and moves nothing."}},"required":["description","quantity"]}},"salesOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Sales invoices only. When present the lines and currency come from the confirmed or delivered order and `items`/`currencyCode` must be omitted."},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Supplier bills only."}},"required":["number","legalEntityId","partyId","issueDate"]},"InvoiceUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer for sales documents, supplier for purchase documents."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"issueDate":{"type":"string","format":"date","description":"Calendar day."},"dueDate":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"notes":{"type":["string","null"],"maxLength":2000},"warehouseId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Active warehouse of the legal entity where the goods of a direct purchase arrive or those of a direct sale leave. Omitted for an invoice of an order: the order has its own."},"priceListId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Sales invoices without an order: the list a direct sale is priced by; saving one needs pricing.read. Each line with an article the list prices is the list price or an agreed price recorded with authorization, and its delivery carries those prices to the order it writes."},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string","maxLength":500},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Price of one unit. Required unless the line states discountPercent. On a sales invoice that names a price list, for an article the list prices: a value other than the list price is an agreed price and needs sales.price.override (403 PRICE_OVERRIDE_DENIED) and priceReason (400 PRICE_REASON_REQUIRED); the same value the draft already had agreed, with the same quantity, is kept without deciding again."},"discountPercent":{"type":"string","pattern":"^(100(\\.0{1,4})?|[0-9]{1,2}(\\.[0-9]{1,4})?)$","description":"Sales invoices that name a price list, on a line with an article: a discount on the list price in force, instead of unitPrice and never with it. The service applies it once and stores the agreed unit price; a result with more than six decimals is refused (409 PRICE_DISCOUNT_NOT_EXACT). Needs sales.price.override and priceReason."},"priceReason":{"type":"string","minLength":1,"maxLength":500,"description":"Sales invoices that name a price list, on a line with an article: why its price is not the list price."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Article of the line. Saving an invoice moves no inventory."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Unit (IMEI) reference only."},"devices":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","description":"Stored in capitals."},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with a valid check digit."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"Second IMEI of the same phone: one unit, never two. Different from imei1."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"Condition the unit will be received with. Its SKU proposes it: left out, the one the SKU states is saved; where the SKU states none it must be given (409 UNIT_CONDITION_REQUIRED), because nothing is assumed to be new. A value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH). Read back: null only for a device saved before conditions were asked."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"Grade of the unit, optional. The SKU proposes its own; a value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH)."}},"required":[]},"description":"Supplier bills without a purchase order: the devices of a serialized line, typed by their identifiers. They are not units until the bill is confirmed with its receipt. At most as many as the line bills, 100 in the invoice, and no identifier twice."},"unitIds":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Units that exist. On a supplier bill with a purchase order: units that order received and no other bill names. On a sales invoice without an order: units of the article, available in the invoice warehouse, that the direct sale will deliver. Saving them reserves and moves nothing."}},"required":["description","quantity"]}},"salesOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","legalEntityId","partyId","issueDate","expectedVersion"]},"InvoiceReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"posReceiptLinked":{"type":"boolean","description":"A register receipt of the invoiced order was recorded as its payment."}},"required":["id","status","version","createdAt","updatedAt"]},"Invoice":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"salesOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"posReceiptId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Register receipt that collected the invoiced order, when there is one."},"posReceiptLinked":{"type":"boolean"},"warehouseId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"issueDate":{"type":"string","format":"date","description":"Calendar day."},"dueDate":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"notes":{"type":["string","null"],"maxLength":2000},"total":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"applied":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"balance":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Total minus applications. Zero when void."},"settlement":{"enum":["UNPAID","PARTIALLY_PAID","PAID",null],"description":"Derived for issued invoices; null otherwise."},"fulfilment":{"type":"object","additionalProperties":false,"properties":{"kind":{"enum":["RECEIPT","DELIVERY"]},"state":{"enum":["NONE","DRAFT","PENDING","PARTIAL","DONE","CANCELLED"],"description":"NONE: the invoice moves nothing. DRAFT: devices typed or units chosen, nothing moved. PENDING: the goods have not arrived or left yet. PARTIAL: some have. DONE: all of them. CANCELLED: the order behind the invoice was cancelled."},"orderStatus":{"type":["string","null"]},"unitsRequired":{"type":"integer"},"unitCount":{"type":"integer"},"devicesTyped":{"type":"integer"}},"required":["kind","state","orderStatus","unitsRequired","unitCount","devicesTyped"],"description":"Only in the record of one invoice, not in listings: what became of the goods it bills."},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"position":{"type":"integer","minimum":1},"description":{"type":"string"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"lineTotal":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"listUnitPrice":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Reference: the list price the line was settled against. For a negotiated line it is a snapshot and does not follow the list. Null on an invoice line that has no list reference."},"priceNegotiated":{"type":"boolean","description":"True when the agreed unit price is not the list price. Such a line keeps its price through confirmation, delivery, invoicing and collection."},"discountPercent":{"type":["string","null"],"pattern":"^(100|[0-9]{1,2})\\.[0-9]{4}$","description":"The discount the price was stated as, when it was stated as one."},"discountAmount":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"What one unit is discounted by: list price minus agreed price. Null when the agreed price is not below the list price."},"priceReason":{"type":["string","null"],"maxLength":500},"priceOrigin":{"enum":["QUOTATION","SALES_ORDER","SALES_INVOICE",null],"type":["string","null"],"description":"The document the price was negotiated in. A line carried to another document keeps it."},"trackingMode":{"enum":["SERIALIZED","QUANTITY","NONE",null],"description":"How the article of the line is tracked; null when the line names none."},"unitsRequired":{"type":["integer","null"],"description":"Units a serialized line bills; null for any other line."},"unitCount":{"type":"integer","description":"Units the line carries: chosen, reserved, delivered or received."},"devices":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"serialNumber":{"type":["string","null"],"pattern":"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$","description":"Stored in capitals."},"imei1":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"15 digits with a valid check digit."},"imei2":{"type":["string","null"],"pattern":"^[0-9]{15}$","description":"Second IMEI of the same phone: one unit, never two. Different from imei1."},"condition":{"type":["string","null"],"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS",null],"description":"Condition the unit will be received with. Its SKU proposes it: left out, the one the SKU states is saved; where the SKU states none it must be given (409 UNIT_CONDITION_REQUIRED), because nothing is assumed to be new. A value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH). Read back: null only for a device saved before conditions were asked."},"grade":{"type":["string","null"],"enum":["A","B","C",null],"description":"Grade of the unit, optional. The SKU proposes its own; a value other than the one the SKU states is refused (409 UNIT_CONDITION_MISMATCH)."}},"required":[]},"description":"Devices typed on the draft of a direct purchase and not received yet. Not units."},"units":{"type":["array","null"],"description":"The units of the line. Null for a reader without inventory.read and inventory.serials.read: the counts are still given, the identifiers are not.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS"]},"grade":{"type":["string","null"],"enum":["A","B","C",null]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"state":{"enum":["SELECTED","RESERVED","DELIVERED","RECEIVED","RELEASED"],"description":"SELECTED: chosen on a draft, nothing reserved. RESERVED: held by the order of the invoice, still in the warehouse. DELIVERED: left with the sale. RECEIVED: came in with the purchase. RELEASED: the invoice was issued with the unit and its order let it go afterwards, undelivered; the invoice keeps naming it."},"eligible":{"type":"boolean","description":"For SELECTED: whether the unit could still leave from the invoice warehouse."}},"required":["id","serialNumber","imei1","imei2","condition","grade","status","state"]}}},"required":["id","position","description","quantity","unitPrice","lineTotal","variantId","inventoryUnitId"]}},"applications":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"paymentId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"creditId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sourceNumber":{"type":"string"},"fromPosReceipt":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","amount","paymentId","creditId","sourceNumber","fromPosReceipt","createdAt"]}}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","warehouseId","currencyCode","issueDate","dueDate","notes","total","applied","balance","settlement","items","applications"]},"InvoicePage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"PaymentInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer for sales documents, supplier for purchase documents."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"paidOn":{"type":"string","format":"date","description":"Calendar day."},"reference":{"type":["string","null"],"maxLength":200,"description":"Voucher, transfer or cheque reference. Anything shaped like a card number is refused."},"notes":{"type":["string","null"],"maxLength":2000},"applications":{"type":"array","maxItems":50,"description":"One entry per invoice of the same party, legal entity, currency and side.","items":{"type":"object","additionalProperties":false,"properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["invoiceId","amount"]}},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Money account of the legal entity the payment lands in (customers) or leaves from (suppliers). Its kind must fit the method. Defaults to the account mapped to the method. Refused when the entity keeps no books."},"cardKind":{"enum":["DEBIT","CREDIT",null],"description":"Only for CARD."},"status":{"enum":["RECORDED","PENDING"],"default":"RECORDED","description":"PENDING is money announced and not confirmed: it carries no applications, settles nothing and posts no entry until confirmed."}},"required":["number","legalEntityId","partyId","currencyCode","amount","method","paidOn"]},"ApplicationsInput":{"type":"object","additionalProperties":false,"properties":{"applications":{"type":"array","maxItems":50,"description":"One entry per invoice of the same party, legal entity, currency and side.","items":{"type":"object","additionalProperties":false,"properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["invoiceId","amount"]},"minItems":1}},"required":["applications"]},"FinanceReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"type":"string"},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","version","createdAt","updatedAt"]},"Payment":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["PENDING","RECORDED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"applied":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unapplied":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Amount minus applications. Zero when void or while pending."},"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"cardKind":{"enum":["DEBIT","CREDIT",null]},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Null when the entity keeps no books."},"paidOn":{"type":"string","format":"date","description":"Calendar day."},"reference":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":2000},"posReceiptId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Set when this payment mirrors a register receipt; never created by hand."},"applications":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"invoiceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"invoiceNumber":{"type":"string"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","invoiceId","invoiceNumber","amount","createdAt"]}}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","currencyCode","amount","applied","unapplied","method","cardKind","accountId","paidOn","reference","notes","posReceiptId","applications"]},"PaymentPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"CreditInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer for sales documents, supplier for purchase documents."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reasonType":{"enum":["RETURN","PRICE_ADJUSTMENT","AGREEMENT","BONUS","OTHER","COST_CORRECTION"],"description":"COST_CORRECTION, supplier credits only: the credit lowers what specific received goods cost and names them in costLines. Every other reason is financial and never changes inventory."},"reason":{"type":"string","maxLength":1000},"originInvoiceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierReturnId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Supplier credits only. A reference: it neither ships nor requires the return."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Reference only; a credit moves no inventory."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Unit (IMEI) reference only."},"costLines":{"type":"array","minItems":1,"maxItems":50,"description":"Supplier credits whose reason is COST_CORRECTION, and only those: the receipt lines the credit corrects and how much of it each takes. The amounts add up to the credit. A line may name one serialized unit of that receipt. Goods received from the same supplier, entity and currency.","items":{"type":"object","additionalProperties":false,"properties":{"receiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["receiptItemId","amount"]}}},"required":["number","legalEntityId","partyId","currencyCode","amount","reasonType","reason"]},"CreditUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"partyId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer for sales documents, supplier for purchase documents."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reasonType":{"enum":["RETURN","PRICE_ADJUSTMENT","AGREEMENT","BONUS","OTHER","COST_CORRECTION"],"description":"COST_CORRECTION, supplier credits only: the credit lowers what specific received goods cost and names them in costLines. Every other reason is financial and never changes inventory."},"reason":{"type":"string","maxLength":1000},"originInvoiceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierReturnId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Supplier credits only. A reference: it neither ships nor requires the return."},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Reference only; a credit moves no inventory."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Unit (IMEI) reference only."},"costLines":{"type":"array","minItems":1,"maxItems":50,"description":"Supplier credits whose reason is COST_CORRECTION, and only those: the receipt lines the credit corrects and how much of it each takes. The amounts add up to the credit. A line may name one serialized unit of that receipt. Goods received from the same supplier, entity and currency.","items":{"type":"object","additionalProperties":false,"properties":{"receiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["receiptItemId","amount"]}},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","legalEntityId","partyId","currencyCode","amount","reasonType","reason","expectedVersion"]},"CreditRecognitionInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"documentReference":{"type":"string","maxLength":200,"description":"Number of the real document that grants the credit."},"recognizedOn":{"type":"string","format":"date","description":"Calendar day."}},"required":["expectedVersion","documentReference","recognizedOn"]},"CreditRefundInput":{"type":"object","additionalProperties":false,"properties":{"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"refundedOn":{"type":["string","null"],"format":"date","description":"Required, except with posSessionId: cash leaves the till now and the refund is dated today."},"reference":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":2000},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Money account the refund leaves from (customer credits) or enters (supplier credits). Defaults to the account mapped to the method. A customer refund in CASH from the cash account of the tills must name posSessionId instead: 409 CASH_SESSION_REQUIRED."},"posSessionId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Customer credits, CASH only: the open till session the cash leaves. It must belong to the acting user and to the entity and currency of the credit, and hold the cash. The refund, the cash movement of the session and its expected cash change together, with one ledger entry. Needs pos.cash.move and sales.create besides the right to refund."},"expectedSessionVersion":{"type":["integer","null"],"minimum":1,"description":"Version of that session; required with posSessionId."}},"required":["amount","method"]},"Credit":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["REQUESTED","RECOGNIZED","REJECTED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"applied":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"refunded":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"available":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Amount minus applications and refunds, only while RECOGNIZED. A request is not a balance."},"reasonType":{"enum":["RETURN","PRICE_ADJUSTMENT","AGREEMENT","BONUS","OTHER","COST_CORRECTION"],"description":"COST_CORRECTION, supplier credits only: the credit lowers what specific received goods cost and names them in costLines. Every other reason is financial and never changes inventory."},"reason":{"type":"string"},"documentReference":{"type":["string","null"]},"recognizedOn":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"originInvoiceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierReturnId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"costLines":{"type":"array","description":"Supplier credits: the receipt lines a cost correction names.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderNumber":{"type":"string"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"serialNumber":{"type":["string","null"]},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["id","receiptItemId","purchaseOrderId","purchaseOrderNumber","variantId","sku","productName","inventoryUnitId","serialNumber","amount"]}},"costAdjustments":{"type":"array","description":"Supplier credits: how a recognised cost correction was distributed, and its reversal if the credit was voided.","items":{"$ref":"#/components/schemas/CostAdjustment"}},"applications":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"invoiceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"invoiceNumber":{"type":"string"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","invoiceId","invoiceNumber","amount","createdAt"]}},"refunds":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"refundedOn":{"type":"string","format":"date","description":"Calendar day."},"reference":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":2000},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"cashMovementId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Cash movement of the till session the refund left, when it left a till."},"posSessionId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"posRegisterName":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","amount","method","refundedOn","reference","notes","accountId","cashMovementId","posSessionId","posRegisterName","createdAt"]}}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","currencyCode","amount","applied","refunded","available","reasonType","reason","documentReference","recognizedOn","originInvoiceId","variantId","inventoryUnitId","applications","refunds"]},"CreditPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Credit"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"SupplierReturnInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reason":{"type":"string","maxLength":1000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."}},"required":["variantId","quantity"]}}},"required":["number","legalEntityId","supplierId","warehouseId","reason","items"]},"SupplierReturnUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reason":{"type":"string","maxLength":1000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."}},"required":["variantId","quantity"]}},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","legalEntityId","supplierId","warehouseId","reason","items","expectedVersion"]},"SupplierReturnShipInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"units":{"type":"array","maxItems":100,"description":"Exact units leaving for every serialized line; quantity lines take none.","items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","unitIds"]}}},"required":["expectedVersion"]},"SupplierReturnReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","AUTHORIZED","SHIPPED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","version","createdAt","updatedAt"]},"SupplierReturn":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","AUTHORIZED","SHIPPED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reason":{"type":"string"},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"trackingMode":{"enum":["QUANTITY","SERIALIZED"]},"unitIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"movementIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":"Ledger movements once shipped."}},"required":["id","variantId","quantity","trackingMode","unitIds","movementIds"]}}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","supplierId","warehouseId","purchaseOrderId","reason","items"]},"SupplierReturnPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SupplierReturn"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"OperationVersionInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1}},"required":["expectedVersion"]},"QuotationInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"validUntil":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Agreed price of one unit, when it is not the list price. Human users only. Not together with discountPercent. Equal to the list price, the line is simply priced by the list. Any other value needs sales.price.override (403 PRICE_OVERRIDE_DENIED) and priceReason (400 PRICE_REASON_REQUIRED)."},"discountPercent":{"type":"string","pattern":"^(100(\\.0{1,4})?|[0-9]{1,2}(\\.[0-9]{1,4})?)$","description":"Discount on the list price in force, above 0 and up to 100, with at most four decimals. Human users only. Not together with unitPrice: the service applies it once and stores the resulting agreed price. A result that needs more than six decimals is refused (409 PRICE_DISCOUNT_NOT_EXACT), never rounded. Needs sales.price.override and priceReason."},"priceReason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the price is not the list price. Only with unitPrice or discountPercent."}},"required":["variantId","quantity"]}}},"required":["number","legalEntityId","customerId","priceListId","items"]},"QuotationUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"validUntil":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Agreed price of one unit, when it is not the list price. Human users only. Not together with discountPercent. Equal to the list price, the line is simply priced by the list. Any other value needs sales.price.override (403 PRICE_OVERRIDE_DENIED) and priceReason (400 PRICE_REASON_REQUIRED)."},"discountPercent":{"type":"string","pattern":"^(100(\\.0{1,4})?|[0-9]{1,2}(\\.[0-9]{1,4})?)$","description":"Discount on the list price in force, above 0 and up to 100, with at most four decimals. Human users only. Not together with unitPrice: the service applies it once and stores the resulting agreed price. A result that needs more than six decimals is refused (409 PRICE_DISCOUNT_NOT_EXACT), never rounded. Needs sales.price.override and priceReason."},"priceReason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the price is not the list price. Only with unitPrice or discountPercent."}},"required":["variantId","quantity"]}},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","legalEntityId","customerId","priceListId","items","expectedVersion"]},"QuotationAcceptInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"order":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["number","warehouseId"],"description":"When present, originates one draft sales order with the quoted lines. Rejected with 409 if any list price differs from the quoted price."}},"required":["expectedVersion"]},"QuotationReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","ACCEPTED","REJECTED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"salesOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","status","version","createdAt","updatedAt"]},"Quotation":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","ACCEPTED","REJECTED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"priceListId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"validUntil":{"type":["string","null"],"format":"date","description":"Calendar day in UTC, inclusive. Null means no expiry."},"expired":{"type":"boolean","description":"Open quotation past its validity day."},"notes":{"type":["string","null"],"maxLength":2000},"salesOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"total":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitPrice":{"type":"string","pattern":"^[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Agreed price of one unit."},"priceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"listUnitPrice":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Reference: the list price the line was settled against. For a negotiated line it is a snapshot and does not follow the list. Null on an invoice line that has no list reference."},"priceNegotiated":{"type":"boolean","description":"True when the agreed unit price is not the list price. Such a line keeps its price through confirmation, delivery, invoicing and collection."},"discountPercent":{"type":["string","null"],"pattern":"^(100|[0-9]{1,2})\\.[0-9]{4}$","description":"The discount the price was stated as, when it was stated as one."},"discountAmount":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"What one unit is discounted by: list price minus agreed price. Null when the agreed price is not below the list price."},"priceReason":{"type":["string","null"],"maxLength":500},"priceOrigin":{"enum":["QUOTATION","SALES_ORDER","SALES_INVOICE",null],"type":["string","null"],"description":"The document the price was negotiated in. A line carried to another document keeps it."},"lineTotal":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."}},"required":["id","variantId","quantity","unitPrice","priceId","listUnitPrice","priceNegotiated","discountPercent","discountAmount","priceReason","priceOrigin","lineTotal"]}}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","customerId","priceListId","currencyCode","validUntil","expired","notes","salesOrderId","total","items"]},"QuotationPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Quotation"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"CommercialReservation":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","RELEASED","CONSUMED"]},"salesOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"orderNumber":{"type":"string"},"orderStatus":{"enum":["DRAFT","CONFIRMED","COMPLETED","CANCELLED"]},"customerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"customerName":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","variantId","warehouseId","quantity","inventoryUnitId","status","salesOrderId","orderNumber","orderStatus","customerId","customerName","createdAt"]},"CommercialReservationPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CommercialReservation"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"TransferOrderInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Active IN_TRANSIT warehouse of the same legal entity."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."}},"required":["variantId","quantity"]}}},"required":["number","legalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","items"]},"TransferOrderUpdateInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Active IN_TRANSIT warehouse of the same legal entity."},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","minItems":1,"maxItems":100,"description":"One line per variant.","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."}},"required":["variantId","quantity"]}},"expectedVersion":{"type":"integer","minimum":1}},"required":["number","legalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","items","expectedVersion"]},"TransferDispatchInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"units":{"type":"array","maxItems":100,"description":"Exact units leaving for every serialized line; quantity lines take none.","items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","unitIds"]}}},"required":["expectedVersion"]},"TransferReceiptInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"reason":{"type":["string","null"],"maxLength":1000,"description":"Required when any line is LOST or RETURNED."},"lines":{"type":"array","minItems":1,"maxItems":100,"description":"Goods resolved now; anything not named stays in transit. Quantity lines send quantity, serialized lines send unitIds.","items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"outcome":{"enum":["RECEIVED","LOST","RETURNED"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","outcome"]}}},"required":["expectedVersion","lines"]},"TransferOrderReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","status","version","createdAt","updatedAt"]},"TransferOrder":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","APPROVED","IN_TRANSIT","PARTIALLY_RECEIVED","RECEIVED","CANCELLED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"number":{"type":"string"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"transitWarehouseId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"notes":{"type":["string","null"],"maxLength":2000},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"trackingMode":{"enum":["QUANTITY","SERIALIZED"]},"dispatched":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"received":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"lost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"returned":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"inTransit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Dispatched minus received, lost and returned."},"units":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"unitId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"outcome":{"enum":["IN_TRANSIT","RECEIVED","LOST","RETURNED"],"description":"What became of the unit this order dispatched."},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"],"description":"State of the unit today, wherever it is now."}},"required":["unitId","outcome"],"description":"A unit this order dispatched, by its own movements: it stays here after it is sold or moved again. Identifiers and state are sent only on the record of the document and only to a reader of inventory.serials.read; everyone else receives the unit references and their count."}}},"required":["id","variantId","quantity","trackingMode","dispatched","received","lost","returned","inTransit","units"]}},"movements":{"type":"array","description":"Inventory ledger movements this order caused.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"kind":{"enum":["DISPATCH","RECEIVED","LOST","RETURNED"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact decimal quantity: at most 12 integer digits and 6 decimals. No rounding."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"movementId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","itemId","kind","quantity","inventoryUnitId","movementId","createdAt"]}},"unitIdentifiers":{"type":"boolean","description":"Only on the record: whether this reader received the identifiers of the units (inventory.serials.read)."}},"required":["id","status","version","createdAt","updatedAt","number","legalEntityId","fromWarehouseId","toWarehouseId","transitWarehouseId","notes","items","movements"]},"TransferOrderPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TransferOrder"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"Ledger":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"baseCurrencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amountScale":{"type":"integer","minimum":0,"maximum":6},"timeZone":{"type":"string","maxLength":64,"description":"IANA time zone. It decides the accounting day of operations that happen now."},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."},"valuationOrigin":{"enum":["EXPLICIT","TENANT_DEFAULT"],"description":"TENANT_DEFAULT: the entity inherited the company default when its books opened. EXPLICIT: the method was chosen for this entity, at opening or later."},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"}},"required":["id","legalEntityId","baseCurrencyCode","amountScale","timeZone","valuationMode","valuationOrigin","startsOn","version","createdAt"]},"LedgerStatus":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityName":{"type":"string"},"enabled":{"type":"boolean","description":"Whether the legal entity keeps books."},"baseCurrencyCode":{"type":["string","null"]},"amountScale":{"type":["integer","null"]},"timeZone":{"type":["string","null"]},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT",null]},"valuationOrigin":{"enum":["EXPLICIT","TENANT_DEFAULT",null]},"startsOn":{"type":["string","null"],"format":"date"},"version":{"type":["integer","null"]}},"required":["id","legalEntityId","legalEntityName","enabled","baseCurrencyCode","amountScale","timeZone","valuationMode","valuationOrigin","startsOn","version"]},"LedgerStatusPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/LedgerStatus"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"LedgerInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"baseCurrencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"amountScale":{"type":"integer","minimum":0,"maximum":6,"description":"Decimals of the currency. Optional for the currencies the platform knows; required otherwise, never assumed."},"timeZone":{"type":"string","maxLength":64,"description":"IANA time zone. It decides the accounting day of operations that happen now."},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT",null],"description":"Omitted or null: the entity inherits the company default in force (409 ACCOUNTING_SETUP_REQUIRED when the company has chosen none). Stated: an explicit choice for this entity, which may differ from the default. BY_PRODUCT is a configuration mode: each product must choose before its stock can be valued."},"startsOn":{"type":"string","format":"date","description":"First accounting day. Nothing is posted before it."},"template":{"enum":["STANDARD","EMPTY"],"default":"STANDARD","description":"STANDARD seeds a generic chart with every mapping set; EMPTY starts with nothing."}},"required":["legalEntityId","baseCurrencyCode","timeZone","startsOn"]},"LedgerUpdateInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"timeZone":{"type":"string","maxLength":64,"description":"IANA time zone. It decides the accounting day of operations that happen now."},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."}},"required":["expectedVersion","timeZone","valuationMode"]},"Account":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string","maxLength":32},"name":{"type":"string","maxLength":200},"type":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]},"cashCounterpart":{"type":"boolean","description":"Accounting lets a cashier book till movements against this account. Bank and cash accounts are always available; card clearing and cheque accounts never are."},"status":{"enum":["ACTIVE","ARCHIVED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","legalEntityId","code","name","type","kind","cashCounterpart","status","version","createdAt","updatedAt","tenantId"]},"AccountRow":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string","maxLength":32},"name":{"type":"string","maxLength":200},"type":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]},"cashCounterpart":{"type":"boolean","description":"Accounting lets a cashier book till movements against this account. Bank and cash accounts are always available; card clearing and cheque accounts never are."},"status":{"enum":["ACTIVE","ARCHIVED"]},"version":{"type":"integer","minimum":1},"balance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Debit minus credit of everything posted."},"mappings":{"type":"array","items":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."}}},"required":["id","legalEntityId","code","name","type","kind","cashCounterpart","status","version","balance","mappings"]},"AccountPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AccountRow"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"AccountInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$"},"name":{"type":"string","maxLength":200},"type":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null],"description":"Only an ASSET account can hold money."},"cashCounterpart":{"type":["boolean","null"],"description":"Lets a cashier book till movements against the account. Only for accounts that hold no money."}},"required":["legalEntityId","code","name","type"]},"AccountUpdateInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"name":{"type":"string","maxLength":200},"status":{"enum":["ACTIVE","ARCHIVED"],"description":"A mapped account cannot be archived. Code, type and kind never change."},"cashCounterpart":{"type":["boolean","null"],"description":"Omitted or null keeps the current value."}},"required":["expectedVersion","name"]},"AccountingMapping":{"type":"object","additionalProperties":false,"properties":{"id":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"key":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"accountCode":{"type":["string","null"]},"accountName":{"type":["string","null"]}},"required":["id","key","accountId","accountCode","accountName"]},"AccountingMappingPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AccountingMapping"}},"nextCursor":{"type":"null"}},"required":["items","nextCursor"]},"AccountingMappingsInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"mappings":{"type":"array","minItems":1,"maxItems":64,"items":{"type":"object","additionalProperties":false,"properties":{"key":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["key","accountId"]}}},"required":["legalEntityId","mappings"]},"AccountingMappingsReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"mappings":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"key":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["key","accountId"]}}},"required":["id","legalEntityId","mappings"]},"FiscalYearInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string","maxLength":64},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"endsOn":{"type":"string","format":"date","description":"The year is cut into calendar months; at most 24. Years never overlap."}},"required":["legalEntityId","name","startsOn","endsOn"]},"FiscalYearReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"periods":{"type":"integer","minimum":1}},"required":["id","legalEntityId","name","periods"]},"AccountingPeriod":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"endsOn":{"type":"string","format":"date","description":"Calendar day."},"status":{"enum":["OPEN","CLOSED"]},"version":{"type":"integer","minimum":1},"closedAt":{"type":["string","null"],"format":"date-time"},"entries":{"type":"integer","minimum":0,"description":"Posted entries dated in the period."}},"required":["id","name","startsOn","endsOn","status","version","closedAt","entries"]},"AccountingPeriodReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fiscalYearId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"endsOn":{"type":"string","format":"date","description":"Calendar day."},"status":{"enum":["OPEN","CLOSED"]},"version":{"type":"integer","minimum":1},"closedBy":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"closedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","legalEntityId","fiscalYearId","name","startsOn","endsOn","status","version","closedBy","closedAt","createdAt","updatedAt"]},"FiscalYear":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"endsOn":{"type":"string","format":"date","description":"Calendar day."},"status":{"enum":["OPEN","CLOSED"]},"version":{"type":"integer","minimum":1},"periods":{"type":"array","items":{"$ref":"#/components/schemas/AccountingPeriod"}}},"required":["id","legalEntityId","name","startsOn","endsOn","status","version","periods"]},"FiscalYearPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FiscalYear"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"FiscalYearClosed":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"startsOn":{"type":"string","format":"date","description":"Calendar day."},"endsOn":{"type":"string","format":"date","description":"Calendar day."},"status":{"enum":["CLOSED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closingEntryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Entry that moved the result of the year to retained earnings; null when it was zero."}},"required":["id","tenantId","legalEntityId","name","startsOn","endsOn","status","version","createdAt","updatedAt","closingEntryId"]},"JournalEntryInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"type":{"enum":["MANUAL","OPENING"],"default":"MANUAL"},"entryDate":{"type":"string","format":"date","description":"Calendar day."},"description":{"type":"string","maxLength":500},"lines":{"type":"array","minItems":2,"maxItems":200,"description":"Each line has exactly one side. Debits equal credits to the last unit.","items":{"type":"object","additionalProperties":false,"properties":{"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"debit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"credit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"memo":{"type":["string","null"],"maxLength":300}},"required":["accountId"]}}},"required":["legalEntityId","entryDate","description","lines"]},"JournalEntry":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sequence":{"type":["integer","null"],"description":"Consecutive number within the ledger, assigned when the entry is posted."},"entryDate":{"type":"string","format":"date","description":"Calendar day."},"periodName":{"type":["string","null"]},"type":{"enum":["OPENING","MANUAL","OPERATION","REVERSAL","CLOSING"]},"status":{"enum":["DRAFT","POSTED","REJECTED"]},"sourceType":{"type":["string","null"],"description":"Kind of operation that wrote the entry: INVOICE, PAYMENT, POS_RECEIPT, INVENTORY_MOVEMENT..."},"sourceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"description":{"type":"string"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"total":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reversesEntryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reversedByEntryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"linkedEntryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The other side of a move between two legal entities, in the other ledger."},"preparedBy":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"postedBy":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"postedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"version":{"type":"integer","minimum":1},"lines":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"lineNo":{"type":"integer","minimum":1},"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"accountCode":{"type":"string"},"accountName":{"type":"string"},"debit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"credit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"memo":{"type":["string","null"]}},"required":["lineNo","accountId","accountCode","accountName","debit","credit","memo"]}}},"required":["id","legalEntityId","sequence","entryDate","periodName","type","status","sourceType","sourceId","description","currencyCode","total","reversesEntryId","reversedByEntryId","linkedEntryId","preparedBy","postedBy","postedAt","createdAt","version","lines"]},"JournalEntryPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/JournalEntry"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"JournalEntryRelated":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/JournalEntry"}},"nextCursor":{"type":"null"}},"required":["items","nextCursor"]},"JournalEntryReversalInput":{"type":"object","additionalProperties":false,"properties":{"entryDate":{"type":"string","format":"date","description":"Never before the entry it cancels; its period must be open."},"reason":{"type":"string","maxLength":500}},"required":["entryDate","reason"]},"AccountLedger":{"type":"object","additionalProperties":false,"properties":{"account":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"type":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]}},"required":["id","code","name","type","kind"]},"from":{"type":"string","format":"date","description":"Calendar day."},"to":{"type":"string","format":"date","description":"Calendar day."},"openingBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"closingBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"entryId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sequence":{"type":"integer","minimum":1},"entryDate":{"type":"string","format":"date","description":"Calendar day."},"description":{"type":"string"},"type":{"enum":["OPENING","MANUAL","OPERATION","REVERSAL","CLOSING"]},"sourceType":{"type":["string","null"]},"sourceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"debit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"credit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"memo":{"type":["string","null"]},"balance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Running debit minus credit, opening balance included."}},"required":["id","entryId","sequence","entryDate","description","type","sourceType","sourceId","debit","credit","memo","balance"]}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["account","from","to","openingBalance","closingBalance","items","nextCursor"]},"TrialBalance":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"from":{"type":"string","format":"date","description":"Calendar day."},"to":{"type":"string","format":"date","description":"Calendar day."},"complete":{"type":"boolean","description":"False while anything is listed in `unposted`: the statement must not be presented as complete."},"unposted":{"type":"array","description":"What the books cannot vouch for yet: operations with no entry, stock with no value and entries awaiting approval. Documents older than the ledger are not listed: they enter through the opening entry.","items":{"type":"object","additionalProperties":false,"properties":{"kind":{"enum":["INVOICE","PAYMENT","CREDIT","POS_RECEIPT","STOCK","DRAFT_ENTRY"]},"count":{"type":"integer","minimum":1}},"required":["kind","count"]}},"totalDebit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"totalCredit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"type":{"enum":["ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]},"openingBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"debit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"credit":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"closingBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."}},"required":["id","code","name","type","kind","openingBalance","debit","credit","closingBalance"]}},"nextCursor":{"type":"null"}},"required":["legalEntityId","currencyCode","from","to","complete","unposted","totalDebit","totalCredit","items","nextCursor"]},"Reconciliation":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"complete":{"type":"boolean"},"items":{"type":"array","description":"What the documents hold against what the mapped account holds, shown on the side the operation uses. Documents older than the ledger count: until an opening entry brings them in they show as a difference.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"key":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."},"operationalBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"ledgerBalance":{"type":["string","null"],"pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"difference":{"type":["string","null"],"pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"reconciled":{"type":"boolean"}},"required":["id","key","operationalBalance","ledgerBalance","difference","reconciled"]}},"clearing":{"type":"array","description":"Card vouchers and cheques recorded and not yet settled, against the balance of their account.","items":{"type":"object","additionalProperties":false,"properties":{"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"kind":{"enum":["CARD_CLEARING","CHECKS"]},"ledgerBalance":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"pendingSettlement":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"reconciled":{"type":"boolean"}},"required":["accountId","code","name","kind","ledgerBalance","pendingSettlement","reconciled"]}},"purchases":{"type":"object","additionalProperties":false,"properties":{"receivedNotBilled":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Goods received and valued whose bill has not arrived: no difference yet."},"billedNotReceived":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Supplier bills of orders with nothing received and unmatched: no difference yet."},"unresolved":{"type":"array","description":"Orders with goods received and a bill issued that nobody matched: a cost difference that is not resolved. While any is listed the reconciliation is not complete.","items":{"type":"object","additionalProperties":false,"properties":{"purchaseOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"number":{"type":"string"},"receivedUnmatched":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"billedUnmatched":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"difference":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Billed minus received."}},"required":["purchaseOrderId","number","receivedUnmatched","billedUnmatched","difference"]}}},"required":["receivedNotBilled","billedNotReceived","unresolved"]},"unposted":{"type":"array","description":"What the books cannot vouch for yet: operations with no entry, stock with no value and entries awaiting approval. Documents older than the ledger are not listed: they enter through the opening entry.","items":{"type":"object","additionalProperties":false,"properties":{"kind":{"enum":["INVOICE","PAYMENT","CREDIT","POS_RECEIPT","STOCK","DRAFT_ENTRY"]},"count":{"type":"integer","minimum":1}},"required":["kind","count"]}},"setup":{"type":"object","additionalProperties":false,"properties":{"missingMappings":{"type":"array","items":{"enum":["ACCOUNTS_RECEIVABLE","ACCOUNTS_PAYABLE","SALES_REVENUE","SALES_BRIDGE","SALES_ALLOWANCES","CUSTOMER_ADVANCES","CUSTOMER_CREDITS","PURCHASE_BRIDGE","PURCHASE_ALLOWANCES","PURCHASE_COST_VARIANCE","SUPPLIER_ADVANCES","SUPPLIER_CREDITS","SUPPLIER_RETURNS_BRIDGE","INVENTORY","INVENTORY_IN_TRANSIT","COST_OF_SALES","INVENTORY_ADJUSTMENT","INVENTORY_LOSS","CARD_FEES","CASH_OVER_SHORT","INTERCOMPANY_RECEIVABLE","INTERCOMPANY_PAYABLE","OPENING_BALANCE_EQUITY","RETAINED_EARNINGS","PAYMENT_CASH","PAYMENT_TRANSFER","PAYMENT_CARD","PAYMENT_CHECK","PAYMENT_OTHER"],"description":"What an operation needs an account for. An unmapped key blocks the operations that use it."}},"productsWithoutMethod":{"type":"integer","minimum":0},"categoriesWithMixedMethods":{"type":"integer","minimum":0},"openPeriodToday":{"type":"boolean"}},"required":["missingMappings","productsWithoutMethod","categoriesWithMixedMethods","openPeriodToday"]},"nextCursor":{"type":"null"}},"required":["legalEntityId","currencyCode","complete","items","clearing","purchases","unposted","setup","nextCursor"]},"SettlementInput":{"type":"object","additionalProperties":false,"properties":{"number":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_./-]{0,63}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromAccountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"CARD_CLEARING or CHECKS account."},"toAccountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"BANK account."},"grossAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"What leaves the clearing account. Never more than it holds."},"feeAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Real fee withheld; less than the gross. Default 0."},"settledOn":{"type":"string","format":"date","description":"Calendar day."},"reference":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":2000}},"required":["number","legalEntityId","fromAccountId","toAccountId","grossAmount","settledOn"]},"Settlement":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"number":{"type":"string"},"fromAccountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromAccountName":{"type":"string"},"toAccountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"toAccountName":{"type":"string"},"grossAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"feeAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"netAmount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Gross minus fee: what reaches the bank account."},"settledOn":{"type":"string","format":"date","description":"Calendar day."},"reference":{"type":["string","null"]},"notes":{"type":["string","null"]},"actorType":{"type":"string"},"actorId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","legalEntityId","number","fromAccountId","toAccountId","grossAmount","feeAmount","netAmount","settledOn","reference","notes","createdAt"]},"SettlementPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Settlement"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ValuationPool":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"bucket":{"enum":["STOCK","TRANSIT"],"description":"Stock in hand, or in an IN_TRANSIT warehouse owned by the entity."},"method":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"value":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"averageCost":{"type":["string","null"],"description":"Value divided by quantity, for display only; never used to post."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"openLayers":{"type":"integer","minimum":0,"description":"FIFO layers that still hold quantity."}},"required":["id","variantId","productId","sku","productName","bucket","method","quantity","value","averageCost","currencyCode","openLayers"]},"ValuationPoolPage":{"type":"object","additionalProperties":false,"properties":{"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."},"items":{"type":"array","items":{"$ref":"#/components/schemas/ValuationPool"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["valuationMode","items","nextCursor"]},"ValuationEntry":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"poolId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"bucket":{"enum":["STOCK","TRANSIT"],"description":"Stock in hand, or in an IN_TRANSIT warehouse owned by the entity."},"method":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"movementId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"movementType":{"type":["string","null"]},"source":{"enum":["MOVEMENT","OPENING","TRANSITION","ADJUSTMENT"],"description":"ADJUSTMENT: a purchase cost corrected afterwards. It changes the value the pool holds, never its quantity."},"direction":{"enum":["IN","OUT"]},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"value":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitCost":{"type":["string","null"],"description":"Cost stated, or taken from the purchase order line, when the stock entered."},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The serialized unit (IMEI) the movement carried."},"serialNumber":{"type":["string","null"]},"costAdjustmentId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"poolQuantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"poolValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"consumedLayers":{"type":"array","description":"FIFO layers an exit consumed. They say which costs left, not which physical unit or IMEI.","items":{"type":"object","additionalProperties":false,"properties":{"layerId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"value":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["layerId","quantity","value"]}},"createdAt":{"type":"string","format":"date-time"}},"required":["id","poolId","bucket","method","movementId","movementType","source","direction","quantity","value","unitCost","inventoryUnitId","serialNumber","costAdjustmentId","poolQuantity","poolValue","consumedLayers","createdAt"]},"ValuationEntryPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ValuationEntry"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ValuationPolicy":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"categoryName":{"type":["string","null"]},"method":{"enum":["WEIGHTED_AVERAGE","FIFO",null],"description":"Null: the product has not chosen yet and its stock cannot be valued."},"justification":{"type":["string","null"]},"version":{"type":["integer","null"]},"valued":{"type":"boolean","description":"Once valued, the method changes only through a transition."}},"required":["id","productId","name","categoryId","categoryName","method","justification","version","valued"]},"ValuationPolicyPage":{"type":"object","additionalProperties":false,"properties":{"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."},"items":{"type":"array","items":{"$ref":"#/components/schemas/ValuationPolicy"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["valuationMode","items","nextCursor"]},"ValuationPolicyInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"method":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"justification":{"type":["string","null"],"maxLength":500,"description":"Required when products of the same category end up with different methods."}},"required":["legalEntityId","productId","method"]},"ValuationPolicyReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"method":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"justification":{"type":["string","null"]}},"required":["id","legalEntityId","productId","method","justification"]},"ValuationTransitionInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Omitted to change the method of the whole entity."},"method":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"reason":{"type":"string","maxLength":500}},"required":["legalEntityId","method","reason"]},"ValuationTransition":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"productId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"fromMethod":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"toMethod":{"enum":["WEIGHTED_AVERAGE","FIFO"]},"effectiveOn":{"type":"string","format":"date","description":"Calendar day."},"carriedValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Value carried over unchanged from the old method to the new one."},"pools":{"type":"integer","minimum":0}},"required":["id","legalEntityId","productId","fromMethod","toMethod","effectiveOn","carriedValue","pools"]},"OpeningStockInput":{"type":"object","additionalProperties":false,"properties":{"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"lines":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Zero is accepted only because it is stated."}},"required":["variantId","unitCost"]}}},"required":["legalEntityId","lines"]},"OpeningStock":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"valued":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"bucket":{"enum":["STOCK","TRANSIT"],"description":"Stock in hand, or in an IN_TRANSIT warehouse owned by the entity."},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"value":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."}},"required":["variantId","bucket","quantity","value"]}}},"required":["id","legalEntityId","valued"]},"PaymentComponentInput":{"type":"object","additionalProperties":false,"properties":{"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"cardKind":{"enum":["DEBIT","CREDIT",null],"description":"Required for CARD and only for CARD."},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Destination money account: an active account of the register entity whose kind fits the method (BANK for TRANSFER, CARD_CLEARING for CARD, CHECKS for CHECK, any money account for OTHER). Defaults to the account mapped to the method, so several banks or clearing accounts of one method can be told apart. Cash collected at a till lands in the cash account of the tills and nowhere else. Anything else is refused with 409 PAYMENT_ACCOUNT_INVALID; the choice is validated by the API, whatever the client offered. Refused when the entity keeps no books."},"reference":{"type":["string","null"],"maxLength":120,"description":"Voucher or transfer reference. Required for every method but CASH. Anything shaped like a card number is refused; PAN and CVV are never accepted or stored."}},"required":["method","amount"]},"PosReceiptPayment":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"lineNo":{"type":"integer","minimum":1},"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"cardKind":{"enum":["DEBIT","CREDIT",null]},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Null when the entity keeps no books."},"status":{"enum":["CONFIRMED"],"description":"A counter collection is recorded once it happened."},"reference":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","receiptId","lineNo","method","cardKind","amount","currencyCode","accountId","status","reference","createdAt"]},"PosCashMovementInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"direction":{"enum":["IN","OUT"]},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reason":{"type":"string","maxLength":500},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Account the cash comes from or goes to (a bank deposit, an expense). Required when the entity keeps books and refused otherwise."}},"required":["expectedVersion","direction","amount","reason"]},"PosCashMovement":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionVersion":{"type":"integer","minimum":2},"direction":{"enum":["IN","OUT"]},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reason":{"type":"string"},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"kind":{"enum":["MANUAL","CREDIT_REFUND"],"description":"CREDIT_REFUND: cash a customer refund took out of the till. Its ledger entry is the refund, not a second one."},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","sessionId","sessionVersion","direction","amount","reason","accountId","kind","requestId","createdAt"]},"PosCashMovementRow":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sessionVersion":{"type":"integer","minimum":2},"direction":{"enum":["IN","OUT"]},"amount":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"reason":{"type":"string"},"accountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"kind":{"enum":["MANUAL","CREDIT_REFUND"],"description":"CREDIT_REFUND: cash a customer refund took out of the till. Its ledger entry is the refund, not a second one."},"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"},"creditRefundId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The customer refund this cash left for; null for a manual movement."},"creditId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"creditNumber":{"type":["string","null"]}},"required":["id","tenantId","sessionId","sessionVersion","direction","amount","reason","accountId","kind","requestId","createdAt","creditRefundId","creditId","creditNumber"]},"PosCashMovementPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PosCashMovementRow"}},"nextCursor":{"type":"null"}},"required":["items","nextCursor"]},"ValuationDefault":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT",null],"description":"Null: the company has chosen no default; each entity must state its method."},"version":{"type":"integer","minimum":0,"description":"0 while nothing was ever chosen."},"updatedAt":{"type":["string","null"],"format":"date-time"},"entitiesWithoutBooks":{"type":"integer","minimum":0,"description":"Legal entities whose books are not open: the ones a new default will reach."},"entitiesInherited":{"type":"integer","minimum":0},"entitiesExplicit":{"type":"integer","minimum":0},"history":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"version":{"type":"integer","minimum":1},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."},"changedBy":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"changedAt":{"type":"string","format":"date-time"}},"required":["version","valuationMode","changedBy","changedAt"]}}},"required":["id","valuationMode","version","updatedAt","entitiesWithoutBooks","entitiesInherited","entitiesExplicit","history"]},"ValuationDefaultInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":0},"valuationMode":{"enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"],"description":"BY_PRODUCT is a configuration mode: each product must choose FIFO or WEIGHTED_AVERAGE before its stock can be valued."}},"required":["expectedVersion","valuationMode"]},"PaymentOptions":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"enabled":{"type":"boolean","description":"Whether the entity keeps books. Without books there is no account to choose."},"currencyCode":{"type":["string","null"]},"tillAccountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Cash account of the tills: cash collected at a counter always lands here."},"hasTills":{"type":"boolean"},"collection":{"type":"array","description":"One entry per payment method, in the order CASH, TRANSFER, CARD, CHECK, OTHER.","items":{"type":"object","additionalProperties":false,"properties":{"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"defaultAccountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The account mapped to the method: preselected, not imposed."},"accounts":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]}},"required":["id","code","name","kind"]}}},"required":["method","defaultAccountId","accounts"]}},"disbursement":{"type":"array","description":"One entry per payment method, in the order CASH, TRANSFER, CARD, CHECK, OTHER.","items":{"type":"object","additionalProperties":false,"properties":{"method":{"enum":["CASH","TRANSFER","CARD","CHECK","OTHER"]},"defaultAccountId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The account mapped to the method: preselected, not imposed."},"accounts":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]}},"required":["id","code","name","kind"]}}},"required":["method","defaultAccountId","accounts"]}},"cashCounterparts":{"type":"array","description":"Accounts a till movement may be booked against.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"code":{"type":"string"},"name":{"type":"string"},"kind":{"enum":["CASH","BANK","CARD_CLEARING","CHECKS",null]}},"required":["id","code","name","kind"]}}},"required":["id","legalEntityId","enabled","currencyCode","tillAccountId","hasTills","collection","disbursement","cashCounterparts"]},"CostAdjustment":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sourceType":{"enum":["SUPPLIER_CREDIT","SUPPLIER_BILL"]},"sourceId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sourceNumber":{"type":["string","null"]},"reversesAdjustmentId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"reversedByAdjustmentId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"entryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Ledger entry that carries the adjustment; null when every difference was zero."},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"adjustedOn":{"type":"string","format":"date","description":"Calendar day."},"total":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"stockAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"transitAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"varianceAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"reason":{"type":["string","null"]},"adjustedBy":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"createdAt":{"type":"string","format":"date-time"},"lines":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"lineNo":{"type":"integer","minimum":1},"receiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderNumber":{"type":"string"},"inventoryUnitId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"serialNumber":{"type":["string","null"]},"invoiceItemId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The bill line the receipt line was matched with."},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"receivedValue":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"What the ledger valued the receipt at when it entered, before any correction."},"billedValue":{"type":["string","null"]},"delta":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Signed correction of the line: negative lowers the cost."},"stockAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Part that changed the value of stock still in hand."},"transitAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Part that changed the value of stock in transit."},"varianceAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Part of goods that had already left: posted to the cost variance account."},"heldQuantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Quantity of the receipt the cost flow still found in the entity. Under FIFO it is what remains of the cost layers of the receipt, which need not be the same physical units."},"matchActive":{"type":"boolean"}},"required":["id","lineNo","receiptItemId","receiptId","purchaseOrderId","purchaseOrderNumber","inventoryUnitId","serialNumber","invoiceItemId","variantId","sku","productName","quantity","receivedValue","billedValue","delta","stockAmount","transitAmount","varianceAmount","heldQuantity","matchActive"]}}},"required":["id","legalEntityId","sourceType","sourceId","sourceNumber","reversesAdjustmentId","reversedByAdjustmentId","entryId","currencyCode","adjustedOn","total","stockAmount","transitAmount","varianceAmount","reason","adjustedBy","createdAt","lines"]},"CostAdjustmentPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CostAdjustment"}},"nextCursor":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["items","nextCursor"]},"ReceivedLines":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"number":{"type":"string"},"supplierId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"items":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Receipt line: what a cost correction or a bill line names."},"receiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receivedAt":{"type":"string","format":"date-time"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"trackingMode":{"enum":["NONE","QUANTITY","SERIALIZED"]},"receivedValue":{"type":["string","null"],"description":"Null: the ledger never valued this receipt, so its cost cannot be corrected."},"adjustments":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Sum of the corrections already applied."},"matched":{"type":"boolean","description":"Already matched with a bill line."},"units":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"serialNumber":{"type":"string"},"status":{"type":"string"}},"required":["id","serialNumber","status"]}}},"required":["id","receiptId","receivedAt","variantId","sku","productName","quantity","unitCost","trackingMode","receivedValue","adjustments","matched","units"]}},"nextCursor":{"type":"null"}},"required":["id","purchaseOrderId","number","supplierId","legalEntityId","currencyCode","items","nextCursor"]},"ReceiptMatching":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"number":{"type":"string"},"status":{"enum":["DRAFT","ISSUED","VOID"]},"version":{"type":"integer","minimum":1},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$"},"enabled":{"type":"boolean","description":"Whether the entity keeps books."},"lines":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"invoiceItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"position":{"type":"integer","minimum":1},"description":{"type":"string"},"variantId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"lineTotal":{"type":"string","pattern":"^[0-9]+\\.[0-9]{12}$","description":"Exact product of quantity and unit price with 12 decimals."},"matched":{"type":"boolean"}},"required":["invoiceItemId","position","description","variantId","quantity","unitPrice","lineTotal","matched"]}},"candidates":{"type":"array","description":"Receipt lines of the bill order.","items":{"type":"object","additionalProperties":false,"properties":{"receiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receivedAt":{"type":"string","format":"date-time"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"unitCost":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$","description":"Exact amount: at most 12 integer digits and 6 decimals. No rounding, tax or FX."},"receivedValue":{"type":["string","null"]},"matched":{"type":"boolean"}},"required":["receiptItemId","receiptId","receivedAt","variantId","sku","productName","quantity","unitCost","receivedValue","matched"]}},"adjustments":{"type":"array","items":{"$ref":"#/components/schemas/CostAdjustment"}}},"required":["id","number","status","version","legalEntityId","purchaseOrderId","currencyCode","enabled","lines","candidates","adjustments"]},"ReceiptMatchInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"matches":{"type":"array","minItems":1,"maxItems":100,"description":"Each bill line with the receipt lines it invoices. Same variant and the same total quantity, or 409 COST_MATCH_MISMATCH.","items":{"type":"object","additionalProperties":false,"properties":{"invoiceItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receiptItemIds":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["invoiceItemId","receiptItemIds"]}}},"required":["expectedVersion","matches"]},"ReceiptMatchResult":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ISSUED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"adjustmentId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"total":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Billed minus received, over the lines matched."},"stockAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"transitAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."},"varianceAmount":{"type":"string","pattern":"^-?[0-9]{1,12}(\\.[0-9]{1,6})?$","description":"Exact signed amount in the ledger currency: debit minus credit unless stated."}},"required":["id","status","version","createdAt","updatedAt","adjustmentId","total","stockAmount","transitAmount","varianceAmount"]},"CostReversalInput":{"type":"object","additionalProperties":false,"properties":{"reason":{"type":"string","maxLength":500}},"required":["reason"]},"ExpenseRecognitionInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"accountId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Expense or asset account of the ledger the bill is charged to."}},"required":["expectedVersion","accountId"]},"InvoiceRecognition":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ISSUED"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"entryId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}},"required":["id","status","version","createdAt","updatedAt","entryId"]},"InvoiceFulfilmentInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"orderNumber":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,63}$","description":"Number of the order the confirmation writes. Defaults to the invoice number said as orders are numbered: slashes as hyphens, and FC- (purchase) or FV- (sale) before a number that does not start with a letter. Not accepted when the invoice already has its order."}},"required":["expectedVersion"]},"InvoiceFulfilmentReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"posReceiptLinked":{"type":"boolean"},"salesOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"salesOrderNumber":{"type":"string"},"purchaseOrderId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"purchaseOrderNumber":{"type":"string"},"goodsReceiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitCount":{"type":"integer","description":"Units that entered or left with the invoice."}},"required":["id","status","version","createdAt","updatedAt","unitCount"]},"InvoiceReceivedUnitsInput":{"type":"object","additionalProperties":false,"properties":{"expectedVersion":{"type":"integer","minimum":1},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Line of the bill."},"unitIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"required":["itemId","unitIds"]}}},"required":["expectedVersion","items"]},"InvoiceUnitsReceipt":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["DRAFT","ISSUED","VOID"]},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"unitCount":{"type":"integer","description":"Units named by this request."}},"required":["id","status","version","createdAt","updatedAt","unitCount"]},"ReceivedUnit":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"condition":{"enum":["NEW","USED","REFURBISHED","OPEN_BOX","AS_IS"]},"grade":{"type":["string","null"],"enum":["A","B","C",null]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"goodsReceiptId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"goodsReceiptItemId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"receivedAt":{"type":"string","format":"date-time"},"invoiceId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Supplier bill that already names the unit; null while no bill does."}},"required":["id","variantId","serialNumber","imei1","imei2","condition","grade","status","goodsReceiptId","goodsReceiptItemId","receivedAt","invoiceId"]},"ReceivedUnitPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedUnit"}},"nextCursor":{"type":"null"}},"required":["items","nextCursor"]},"UnitTrace":{"type":"object","additionalProperties":false,"properties":{"unit":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"sku":{"type":"string"},"productName":{"type":"string"},"storage":{"type":["string","null"]},"color":{"type":["string","null"]},"simType":{"type":"string"},"serialNumber":{"type":["string","null"]},"imei1":{"type":["string","null"]},"imei2":{"type":["string","null"]},"condition":{"type":"string"},"grade":{"type":["string","null"]},"status":{"enum":["AVAILABLE","RESERVED","SOLD","IN_TRANSIT","DAMAGED","RETURNED","RMA","LOST","QUARANTINED"]},"version":{"type":"integer","minimum":0},"legalEntityId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"warehouseName":{"type":["string","null"]}},"required":["id","variantId","sku","productName","storage","color","simType","serialNumber","imei1","imei2","condition","grade","status","version","legalEntityId","warehouseId","warehouseName"]},"access":{"type":"object","additionalProperties":false,"properties":{"purchases":{"type":"boolean"},"sales":{"type":"boolean"},"pos":{"type":"boolean"},"inventory":{"type":"boolean"},"accounting":{"type":"boolean"}},"required":["purchases","sales","pos","inventory","accounting"],"description":"Which modules the reader may open documents of, read in this request. A document of a module that is false is never in the response."},"events":{"type":"array","description":"Movements of the unit and events of its reservations, in the causal order the inventory gave them. Nothing is merged or invented: two documents that tell the same arrival are named by one event.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The movement or the reservation event."},"kind":{"enum":["MOVEMENT","RESERVATION"]},"sequence":{"type":"integer","minimum":1,"description":"Version of the unit after the fact."},"occurredAt":{"type":"string","format":"date-time"},"effect":{"enum":["IN","OUT","HOLD","FREE","CHANGE"],"description":"Entered, left, was held, was freed, or changed where it was."},"fact":{"enum":["PURCHASE_RECEIPT","MANUAL_ENTRY","READMISSION","TRANSFER_OUT","TRANSFER_IN","TRANSFER_RETURNED","IMPORT_OUT","IMPORT_IN","IMPORT_RETURNED","MOVE","RESERVED","RELEASED","RESERVATION_CONSUMED","SALE_DELIVERY","SUPPLIER_RETURN","DAMAGE","LOSS","TRANSIT_LOSS","OTHER"]},"fromWarehouse":{"type":["object","null"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"}},"required":["id","name"]},"toWarehouse":{"type":["object","null"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"name":{"type":"string"}},"required":["id","name"]},"fromStatus":{"type":["string","null"]},"toStatus":{"type":["string","null"]},"documents":{"type":"array","description":"Documents behind the fact that the reader may open, by their identifiers.","items":{"type":"object","additionalProperties":false,"properties":{"type":{"enum":["SUPPLIER_BILL","PURCHASE_ORDER","PURCHASE_RECEIPT","SUPPLIER_RETURN","SALES_INVOICE","SALES_ORDER","POS_RECEIPT","TRANSFER_ORDER","IMPORT_ORDER","JOURNAL_ENTRY"]},"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"number":{"type":["string","null"]},"line":{"type":["integer","null"],"description":"Line that names the unit, from one."}},"required":["type","id","number","line"]}},"withheld":{"type":"array","items":{"enum":["purchases","sales","pos","inventory"]},"description":"Modules that have documents of this fact the reader may not open. Nothing else about them is sent: no number, party, amount, cost or identifier."}},"required":["id","kind","sequence","occurredAt","effect","fact","fromWarehouse","toWarehouse","fromStatus","toStatus","documents","withheld"]}}},"required":["unit","access","events"]},"PriceAdjustment":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"documentType":{"enum":["QUOTATION","SALES_ORDER","SALES_INVOICE"]},"documentId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"documentNumber":{"type":["string","null"]},"variantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"quantity":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"listUnitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"List price the change was measured against."},"previousUnitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Agreed price the line had before."},"unitPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$","description":"Agreed price the line has since."},"discountPercent":{"type":["string","null"],"pattern":"^(100|[0-9]{1,2})\\.[0-9]{4}$"},"discountAmount":{"type":["string","null"],"pattern":"^(0|[1-9][0-9]{0,11})\\.[0-9]{6}$"},"reason":{"type":["string","null"],"description":"Null only when the line went back to the list price."},"changedBy":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"The user who changed the price."},"changedAt":{"type":"string","format":"date-time"}},"required":["id","documentType","documentId","documentNumber","variantId","quantity","listUnitPrice","previousUnitPrice","unitPrice","discountPercent","discountAmount","reason","changedBy","changedAt"]},"PriceAdjustmentPage":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PriceAdjustment"}},"nextCursor":{"type":"null"}},"required":["items","nextCursor"]},"OnboardingInput":{"type":"object","additionalProperties":false,"required":["displayName","companyName","legalEntityName","countryCode","branchName","warehouseName","currencyCode","timeZone","valuationMode","startsOn","fiscalStartsOn","fiscalEndsOn","plan"],"properties":{"displayName":{"type":"string","minLength":1,"maxLength":200},"companyName":{"type":"string","minLength":1,"maxLength":200},"legalEntityName":{"type":"string","minLength":1,"maxLength":200},"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"ISO 3166-1 alpha-2; descriptive only, no tax setup."},"branchName":{"type":"string","minLength":1,"maxLength":200},"warehouseName":{"type":"string","minLength":1,"maxLength":200},"currencyCode":{"type":"string","enum":["USD","EUR","MXN","COP","PEN","ARS","BRL","GBP","CAD","DOP","GTQ","CRC","BOB","UYU","CLP","PYG","JPY"]},"timeZone":{"type":"string","maxLength":64},"valuationMode":{"type":"string","enum":["WEIGHTED_AVERAGE","FIFO","BY_PRODUCT"]},"startsOn":{"type":"string","format":"date","description":"Exact calendar date, 1900–2100."},"fiscalStartsOn":{"type":"string","format":"date","description":"Exact calendar date, 1900–2100."},"fiscalEndsOn":{"type":"string","format":"date","description":"Exact calendar date, 1900–2100."},"plan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]}}},"OnboardingReceipt":{"type":"object","additionalProperties":false,"required":["tenantId","legalEntityId","branchId","warehouseId","priceListId","companyName","completedAt","requestedPlan","effectivePlan","subscriptionStatus"],"properties":{"tenantId":{"type":"string","format":"uuid"},"legalEntityId":{"type":"string","format":"uuid"},"branchId":{"type":"string","format":"uuid"},"warehouseId":{"type":"string","format":"uuid"},"priceListId":{"type":"string","format":"uuid"},"companyName":{"type":"string","minLength":1,"maxLength":200},"completedAt":{"type":"string","format":"date-time"},"requestedPlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"effectivePlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"subscriptionStatus":{"enum":["ACTIVE","PENDING_PAYMENT"]}}},"OnboardingState":{"type":"object","additionalProperties":false,"required":["completed","options"],"properties":{"completed":{"anyOf":[{"$ref":"#/components/schemas/OnboardingReceipt"},{"type":"null"}]},"options":{"type":"object","additionalProperties":false,"required":["countries","currencies","timeZones","plans"],"properties":{"countries":{"type":"array","items":{"type":"object","required":["code","name"],"properties":{"code":{"type":"string"},"name":{"type":"string"}}}},"currencies":{"type":"array","items":{"type":"object","required":["code","name","scale"],"properties":{"code":{"type":"string"},"name":{"type":"string"},"scale":{"type":"integer"}}}},"timeZones":{"type":"array","items":{"type":"string"}},"plans":{"type":"array","items":{"$ref":"#/components/schemas/OnboardingPlan"}}}}}},"OnboardingPlan":{"type":"object","additionalProperties":false,"required":["code","name","description","monthlyPrice","priceCurrency","limits"],"properties":{"code":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string"},"monthlyPrice":{"type":["string","null"]},"priceCurrency":{"type":["string","null"]},"limits":{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":["integer","null"],"minimum":1},"legalEntities":{"type":["integer","null"],"minimum":1},"branches":{"type":["integer","null"],"minimum":1},"warehouses":{"type":["integer","null"],"minimum":1},"products":{"type":["integer","null"],"minimum":1}}}}},"PlatformCompany":{"type":"object","additionalProperties":false,"required":["id","name","subscription"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subscription":{"anyOf":[{"type":"object","additionalProperties":false,"required":["requestedPlan","effectivePlan","status","assignmentType","version","assignedBy","assignedAt","assignmentReason","limits"],"properties":{"requestedPlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"effectivePlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"status":{"enum":["ACTIVE","PENDING_PAYMENT"]},"assignmentType":{"enum":["SELF_SERVICE","COMPLIMENTARY"]},"version":{"type":"integer","minimum":1},"assignedBy":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"assignedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"assignmentReason":{"type":["string","null"],"maxLength":200},"limits":{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":["integer","null"],"minimum":1,"maximum":100000},"legalEntities":{"type":["integer","null"],"minimum":1,"maximum":100000},"branches":{"type":["integer","null"],"minimum":1,"maximum":100000},"warehouses":{"type":["integer","null"],"minimum":1,"maximum":100000},"products":{"type":["integer","null"],"minimum":1,"maximum":100000}}}}},{"type":"null"}]}}},"PlatformCompanies":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PlatformCompany"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}}},"PlatformUsers":{"type":"object","additionalProperties":false,"required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","displayName","contactEmail","status","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contactEmail":{"type":["string","null"]},"status":{"enum":["ACTIVE","DISABLED"]},"createdAt":{"type":"string","format":"date-time"}}}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}}},"PlatformCompanyDetail":{"type":"object","additionalProperties":false,"required":["id","name","subscription","usage","history"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subscription":{"anyOf":[{"type":"object","additionalProperties":false,"required":["requestedPlan","effectivePlan","status","assignmentType","version","assignedBy","assignedAt","assignmentReason","limits"],"properties":{"requestedPlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"effectivePlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"status":{"enum":["ACTIVE","PENDING_PAYMENT"]},"assignmentType":{"enum":["SELF_SERVICE","COMPLIMENTARY"]},"version":{"type":"integer","minimum":1},"assignedBy":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"assignedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"assignmentReason":{"type":["string","null"],"maxLength":200},"limits":{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":["integer","null"],"minimum":1,"maximum":100000},"legalEntities":{"type":["integer","null"],"minimum":1,"maximum":100000},"branches":{"type":["integer","null"],"minimum":1,"maximum":100000},"warehouses":{"type":["integer","null"],"minimum":1,"maximum":100000},"products":{"type":["integer","null"],"minimum":1,"maximum":100000}}}}},{"type":"null"}]},"usage":{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":"integer","minimum":0},"legalEntities":{"type":"integer","minimum":0},"branches":{"type":"integer","minimum":0},"warehouses":{"type":"integer","minimum":0},"products":{"type":"integer","minimum":0}}},"history":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["id","previousPlan","plan","assignedBy","assignedAt","reason","limits"],"properties":{"id":{"type":"string","format":"uuid"},"previousPlan":{"anyOf":[{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},{"type":"null"}]},"plan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"assignedBy":{"type":"string","format":"uuid"},"assignedAt":{"type":"string","format":"date-time"},"reason":{"type":"string"},"limits":{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":["integer","null"],"minimum":1,"maximum":100000},"legalEntities":{"type":["integer","null"],"minimum":1,"maximum":100000},"branches":{"type":["integer","null"],"minimum":1,"maximum":100000},"warehouses":{"type":["integer","null"],"minimum":1,"maximum":100000},"products":{"type":["integer","null"],"minimum":1,"maximum":100000}}}}}}}},"ComplimentaryPlanInput":{"type":"object","additionalProperties":false,"required":["plan","expectedVersion","reason","limits"],"properties":{"plan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"expectedVersion":{"type":"integer","minimum":0,"maximum":2147483646},"reason":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f]+$"},"limits":{"anyOf":[{"type":"object","additionalProperties":false,"required":["users","legalEntities","branches","warehouses","products"],"properties":{"users":{"type":["integer","null"],"minimum":1,"maximum":100000},"legalEntities":{"type":["integer","null"],"minimum":1,"maximum":100000},"branches":{"type":["integer","null"],"minimum":1,"maximum":100000},"warehouses":{"type":["integer","null"],"minimum":1,"maximum":100000},"products":{"type":["integer","null"],"minimum":1,"maximum":100000}}},{"type":"null"}],"description":"Custom capacity only for ENTERPRISE. Null uses the catalog limits."}}},"ComplimentaryPlanAssignment":{"type":"object","additionalProperties":false,"required":["id","tenantId","effectivePlan","status","assignmentType","version"],"properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"effectivePlan":{"type":"string","enum":["FREE","BASIC","PROFESSIONAL","ENTERPRISE"]},"status":{"const":"ACTIVE"},"assignmentType":{"const":"COMPLIMENTARY"},"version":{"type":"integer","minimum":1}}},"PlatformRoles":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","code","name","status"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"status":{"enum":["ACTIVE","DISABLED"]}}}}}},"PlatformMembers":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["membershipId","userId","displayName","userStatus","status","createdAt","current","roles"],"properties":{"membershipId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"userStatus":{"enum":["ACTIVE","DISABLED"]},"status":{"enum":["ACTIVE","SUSPENDED"]},"createdAt":{"type":"string","format":"date-time"},"current":{"type":"boolean"},"roles":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","code","name","status"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"status":{"enum":["ACTIVE","DISABLED"]}}}}}}}}},"PlatformPlans":{"type":"object","additionalProperties":false,"required":["plans"],"properties":{"plans":{"type":"array","items":{"$ref":"#/components/schemas/OnboardingPlan"}}}},"CatalogProductCreateInput":{"type":"object","additionalProperties":false,"required":["name","productType","unitOfMeasure"],"properties":{"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":["string","null"],"maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$","description":"Web identifier, unique per company and kept reserved after archiving. Optional. Omitted or null on creation: generated from the name (accents and symbols removed, words joined by hyphens, at most 160 characters) and, when taken, completed with -2, -3… Stated: used as given, 409 when taken. Omitted or null on update: the product keeps its slug; renaming a product never changes it."},"variantMode":{"enum":["SINGLE","MULTIPLE",null],"description":"SINGLE: an article sold as one SKU. MULTIPLE: an article that holds several versions of itself, each with its own SKU. Omitted or null on creation: MULTIPLE when more than one variant is created with the product, SINGLE otherwise. Omitted or null on update: unchanged. SINGLE is refused (409) while the product has more than one active variant."},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"manufacturerId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"trackInventory":{"type":"boolean","default":false},"trackSerials":{"type":"boolean","default":false},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true},"variants":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogVariantInput"},"description":"Variants created with the product in the same transaction: all of them or nothing. A SKU that is invalid or repeated in the request is a 400; one already taken in the company, archived variants included, is a 409, and neither leaves a product behind. Omitted: the product is created alone, as before, and completed later. With at least one variant the product may be created PUBLISHED; alone it is always a DRAFT."}}},"CatalogProductCreated":{"type":"object","additionalProperties":false,"required":["id","tenantId","status","archivedAt","createdAt","updatedAt","name","slug","productType","categoryId","brandId","manufacturerId","unitOfMeasure","trackInventory","trackSerials","publicationStatus","description","shortDescription","attributes","variantMode","variantCount","singleSku","singleVariantId"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"tenantId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":"string","maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"variantMode":{"enum":["SINGLE","MULTIPLE"],"description":"What the product is in practice: MULTIPLE when it was declared so or has more than one active variant; SINGLE otherwise."},"variantCount":{"type":"integer","minimum":0,"description":"Active variants of the product. Zero: it has no SKU yet."},"singleSku":{"type":["string","null"],"description":"SKU of the only active variant when the product has exactly one; null otherwise."},"singleVariantId":{"type":["string","null"],"format":"uuid","description":"Id of the only active variant when the product has exactly one; null otherwise. Human reads only: API-key projections never carry it."},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"manufacturerId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"trackInventory":{"type":"boolean","default":false},"trackSerials":{"type":"boolean","default":false},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500},"attributes":{"type":"object","description":"Bounded JSON (500 nodes, depth 5, 16000 characters). Reserved credential/prototype keys and secret patterns rejected. Never included in API-key reads.","additionalProperties":true},"variants":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/CatalogVariant"},"description":"The variants created with the product, in the order of the request. Present only when the request carried `variants`; a product created alone answers as it always did."}}},"PublicCatalogProductCreated":{"type":"object","additionalProperties":false,"required":["id","status","createdAt","updatedAt","name","slug","productType","categoryId","brandId","unitOfMeasure","publicationStatus","description","shortDescription"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"status":{"enum":["ACTIVE","ARCHIVED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"name":{"type":"string","maxLength":200,"minLength":1},"slug":{"type":"string","maxLength":160,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"productType":{"enum":["GOOD","SERVICE"]},"categoryId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"brandId":{"type":["string","null"],"format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"unitOfMeasure":{"type":"string","maxLength":16,"pattern":"^[A-Z][A-Z0-9_]{0,15}$"},"publicationStatus":{"enum":["DRAFT","PUBLISHED"],"default":"DRAFT"},"description":{"type":["string","null"],"maxLength":10000},"shortDescription":{"type":["string","null"],"maxLength":500},"variants":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogVariant"},"description":"The variants created with the product, in the order of the request. Present only when the request carried `variants`; a product created alone answers as it always did."}}},"ContactProfile":{"type":"object","additionalProperties":false,"properties":{"contactType":{"type":["string","null"],"enum":["COMPANY","PERSON",null]},"companyName":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$","description":"Legal name."},"tradeName":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"taxIdType":{"type":["string","null"],"enum":["RUC","CEDULA","PASSPORT","OTHER",null],"description":"What the taxId of the record is."},"taxIdTypeOther":{"type":["string","null"],"minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$","description":"Names the identification. Accepted only with taxIdType OTHER."},"website":{"type":["string","null"],"maxLength":500,"pattern":"^[hH][tT][tT][pP][sS]?://[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?(:[0-9]{1,5})?([/?#][^\\s\\\\]*)?$","description":"http or https only, with a host and without credentials."},"mobile":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"language":{"type":["string","null"],"enum":["es","en","pt","fr","other",null]},"primaryContact":{"type":"object","additionalProperties":false,"properties":{"salutation":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"firstName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"lastName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"jobTitle":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"department":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"required":["salutation","firstName","lastName","jobTitle","department"],"description":"The person the record is addressed to. Their email and phone are the email and phone of the record."},"billingAddress":{"type":"object","additionalProperties":false,"properties":{"attention":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"countryCode":{"type":["string","null"],"pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2. Stored in capitals."},"state":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"city":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"street1":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"street2":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"required":["attention","countryCode","state","city","street1","street2","postalCode","phone"]},"shippingAddress":{"type":"object","additionalProperties":false,"properties":{"attention":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"countryCode":{"type":["string","null"],"pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2. Stored in capitals."},"state":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"city":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"street1":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"street2":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"required":["attention","countryCode","state","city","street1","street2","postalCode","phone"],"description":"Its own values: it is never linked to the billing address."},"contactPersons":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"properties":{"firstName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"lastName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"jobTitle":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"department":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"email":{"type":["string","null"],"maxLength":254,"pattern":"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"mobile":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"required":["firstName","lastName","jobTitle","department","email","phone","mobile"]},"description":"Further people, at most 20. Written, each one states at least one value."},"currencyCode":{"type":["string","null"],"pattern":"^[a-zA-Z]{3}$","description":"Preferred ISO 4217 currency among the supported ones, stored in capitals. Documents keep stating their own."},"paymentTermsDays":{"type":["integer","null"],"minimum":0,"maximum":3650,"description":"Informative: no due date, credit or charge is derived from it."},"notes":{"type":["string","null"],"minLength":1,"maxLength":4000,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"tags":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"description":"At most 20, unique without regard to case."},"customFields":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["name","value"],"properties":{"name":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"value":{"type":"string","minLength":1,"maxLength":500,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}}},"description":"At most 20 name/value pairs with unique names."}},"required":["contactType","companyName","tradeName","taxIdType","taxIdTypeOther","website","mobile","language","primaryContact","billingAddress","shippingAddress","contactPersons","currencyCode","paymentTermsDays","notes","tags","customFields"],"description":"Extended record (CONTACTS-1), always whole: null or an empty list where nothing was stated. Descriptive only: it grants no credit and computes no charge or tax."},"ContactProfileInput":{"type":["object","null"],"additionalProperties":false,"properties":{"contactType":{"type":["string","null"],"enum":["COMPANY","PERSON",null]},"companyName":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$","description":"Legal name."},"tradeName":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"taxIdType":{"type":["string","null"],"enum":["RUC","CEDULA","PASSPORT","OTHER",null],"description":"What the taxId of the record is."},"taxIdTypeOther":{"type":["string","null"],"minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$","description":"Names the identification. Accepted only with taxIdType OTHER."},"website":{"type":["string","null"],"maxLength":500,"pattern":"^[hH][tT][tT][pP][sS]?://[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?(:[0-9]{1,5})?([/?#][^\\s\\\\]*)?$","description":"http or https only, with a host and without credentials."},"mobile":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"language":{"type":["string","null"],"enum":["es","en","pt","fr","other",null]},"primaryContact":{"type":["object","null"],"additionalProperties":false,"properties":{"salutation":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"firstName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"lastName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"jobTitle":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"department":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"description":"The person the record is addressed to. Their email and phone are the email and phone of the record."},"billingAddress":{"type":["object","null"],"additionalProperties":false,"properties":{"attention":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"countryCode":{"type":["string","null"],"pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2. Stored in capitals."},"state":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"city":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"street1":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"street2":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}}},"shippingAddress":{"type":["object","null"],"additionalProperties":false,"properties":{"attention":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"countryCode":{"type":["string","null"],"pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2. Stored in capitals."},"state":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"city":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"street1":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"street2":{"type":["string","null"],"minLength":1,"maxLength":200,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"postalCode":{"type":["string","null"],"minLength":1,"maxLength":20,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"description":"Its own values: it is never linked to the billing address."},"contactPersons":{"type":["array","null"],"maxItems":20,"items":{"type":"object","additionalProperties":false,"properties":{"firstName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"lastName":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"jobTitle":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"department":{"type":["string","null"],"minLength":1,"maxLength":100,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"email":{"type":["string","null"],"maxLength":254,"pattern":"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"},"phone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"mobile":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}},"minProperties":1},"description":"Further people, at most 20. Written, each one states at least one value."},"currencyCode":{"type":["string","null"],"pattern":"^[a-zA-Z]{3}$","description":"Preferred ISO 4217 currency among the supported ones, stored in capitals. Documents keep stating their own."},"paymentTermsDays":{"type":["integer","null"],"minimum":0,"maximum":3650,"description":"Informative: no due date, credit or charge is derived from it."},"notes":{"type":["string","null"],"minLength":1,"maxLength":4000,"pattern":"^[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u0009\\u000b-\\u001f\\u007f-\\u009f]*$","description":"May hold several lines."},"tags":{"type":["array","null"],"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"description":"At most 20, unique without regard to case."},"customFields":{"type":["array","null"],"maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["name","value"],"properties":{"name":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"},"value":{"type":"string","minLength":1,"maxLength":500,"pattern":"^[^\\u0000-\\u001f\\u007f-\\u009f]*\\S[^\\u0000-\\u001f\\u007f-\\u009f]*$"}}},"description":"At most 20 name/value pairs with unique names."}},"description":"Extended record (CONTACTS-1), replaced whole when sent: a key left out or null is not stated. Null or {} clears it. Left out of an update, the stored profile is kept; left out of a creation, the profile starts empty. Strings are trimmed and never blank; unknown keys are refused."}}},"x-webhooks-delivery":{"description":"Outgoing HTTPS POST: HMAC-SHA256 using complete signingSecret UTF-8 string over timestamp + \".\" + exact raw body. Header X-Webhook-Signature is v1=<64 lowercase hex>; X-Webhook-Timestamp is Unix seconds; X-Event-Id and X-Request-Id are UUIDv7. Reject stale timestamps (recommended 300s), compare signatures in constant time and deduplicate event_id. Delivery is at least once; 2xx succeeds, other HTTP responses retry up to 5 attempts. No redirects.","envelope":{"$ref":"#/components/schemas/WebhookEnvelope"}},"tags":[{"name":"Sales","description":"Customers and sales orders with price snapshots, reservations and delivery."},{"name":"POS","description":"Human-operated cash registers, sessions, receipts and atomic checkout of confirmed Sales orders."},{"name":"Inventory","description":"Transfer orders between warehouses of one legal entity with transit custody."},{"name":"Reports","description":"Read-only stock, in-transit and balance reports per legal entity."},{"name":"Procurement","description":"Supplier bills, payments made, supplier credits and physical supplier returns."},{"name":"Accounting","description":"Double-entry ledger per legal entity: chart of accounts, mappings, fiscal years and periods, journal, general ledger, trial balance, reconciliation and settlements."},{"name":"Valuation","description":"Inventory valuation per legal entity and variant: moving weighted average and FIFO layers, product policies, controlled method transitions and opening costs."},{"name":"Onboarding","description":"Deliberate self-service setup of a new company."},{"name":"Platform administration","description":"Human global administrators, company plans and account directory."}]}