{"openapi":"3.1.0","info":{"title":"TAHO OMS Customer API","version":"2026-08","description":"Customer-facing APIs for products, inbound ASN, dropship fulfillment, pricing and finance. Every public API credential is bound to exactly one OMS organization and one customer; send that same customerId on every request. Preserve the stable intent key specified by each write endpoint (Idempotency-Key or body operationId); durable request execution uses its original requestId. Browser clients may use CORS only after an exact Origin is registered on their active API credential; server-to-server clients do not need CORS."},"servers":[{"url":"/api/public/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Products","description":"Customer product master"},{"name":"Inbound","description":"Inbound pre-alerts and receiving status"},{"name":"Outbound","description":"Dropship fulfillment orders"},{"name":"Inventory","description":"Available inventory"},{"name":"Pricing","description":"Quotation calculation and customer quotes"},{"name":"Finance","description":"Statements, charges and wallet balances"},{"name":"Portal","description":"Bounded customer dashboard projection"}],"paths":{"/oms/warehouse-allocations":{"get":{"tags":["Portal"],"summary":"Read own requirements and confirmed warehouse choices","description":"Requires portal:read. Pending requirements, outdated allocations and inactive warehouses are excluded from choices.","parameters":[{"name":"customerId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Requirements and eligible choices ordered by priority"}}},"post":{"tags":["Portal"],"summary":"Submit new requirements for OMS warehouse allocation","description":"Requires outbound:write and cookie CSRF protection. Send customerId, operationId, expectedVersion, goodsClass (SMALL/LARGE), services, optional country, maxWeightKg, maxLongestCm and notes. Reuse operationId when retrying. The new version is PENDING until an operator confirms a matching warehouse; previous allocations become unavailable.","responses":{"200":{"description":"Pending requirement saved"},"409":{"description":"Version conflict"}}}},"/oms/customer-orders":{"post":{"tags":["Outbound","Inbound"],"operationId":"receiveOmsCustomerOrder","summary":"Receive a customer OMS order using an allocated warehouse","description":"Use outbound:write for OUTBOUND and inbound:write for INBOUND. The API stores a customer order independently of local WMS. It does not reserve stock, charge money or dispatch to a supplier. Reuse operationId with the same body when retrying; customerId + kind + referenceNo must be unique within the organization.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customerId","referenceNo","kind","operationId","items"],"properties":{"warehouseAssignmentId":{"type":"string","description":"An available assignment returned by /oms/warehouse-allocations; required once customer warehouse requirements are configured."},"customerId":{"type":"string","maxLength":100},"referenceNo":{"type":"string","maxLength":100},"kind":{"type":"string","enum":["INBOUND","OUTBOUND"]},"goodsClass":{"type":"string","enum":["SMALL","LARGE","UNSPECIFIED"],"default":"UNSPECIFIED","description":"Customer-defined goods class. A specified class must match the assigned operating warehouse during delegation."},"operationId":{"type":"string","maxLength":100},"items":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","required":["sku","quantity"],"properties":{"sku":{"type":"string","maxLength":100},"quantity":{"type":"integer","minimum":1,"maximum":1000000}}}},"shipment":{"type":"object","properties":{"recipientName":{"type":"string"},"phone":{"type":"string"},"country":{"type":"string","minLength":2,"maxLength":2},"state":{"type":"string"},"city":{"type":"string"},"postalCode":{"type":"string"},"address1":{"type":"string"},"address2":{"type":"string"},"logisticsChannel":{"type":"string"}}},"notes":{"type":"string","maxLength":2000}}},"example":{"customerId":"your-customer-id","referenceNo":"CLIENT-001","kind":"OUTBOUND","operationId":"intake-CLIENT-001","items":[{"sku":"SKU-001","quantity":2}],"shipment":{"country":"US","recipientName":"Recipient","city":"Ontario","postalCode":"91761","address1":"Example address"}}}}},"responses":{"200":{"description":"Original order returned on retry"},"201":{"description":"Customer order received; no warehouse dispatch"},"400":{"description":"Invalid order"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Credential/customer scope denied"},"409":{"description":"Reference or operation conflict"}}}},"/products":{"get":{"tags":["Products"],"operationId":"listProducts","summary":"List customer products","security":[{"bearerAuth":["products:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Products"],"operationId":"upsertProduct","summary":"Create or update a customer SKU","security":[{"bearerAuth":["products:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for products:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inventory":{"get":{"tags":["Inventory"],"operationId":"listInventory","summary":"Read available GOOD inventory","security":[{"bearerAuth":["inventory:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCode"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/inbound-orders":{"get":{"tags":["Inbound"],"operationId":"listInboundOrders","summary":"List inbound ASNs","security":[{"bearerAuth":["inbound:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCodeList"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Inbound"],"operationId":"createInboundOrder","summary":"Create an inbound ASN","security":[{"bearerAuth":["inbound:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundOrderCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for inbound:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inbound-orders/{id}":{"get":{"tags":["Inbound"],"operationId":"getInboundOrder","summary":"Read inbound status, receipts and labels","security":[{"bearerAuth":["inbound:read"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCode"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Resource not found"}}}},"/outbound-orders":{"get":{"tags":["Outbound"],"operationId":"listOutboundOrders","summary":"List dropship fulfillment orders","security":[{"bearerAuth":["outbound:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCodeList"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Outbound"],"operationId":"createOutboundOrder","summary":"Create a dropship fulfillment order","security":[{"bearerAuth":["outbound:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundOrderCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for outbound:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/outbound-orders/{id}":{"get":{"tags":["Outbound"],"operationId":"getOutboundOrder","summary":"Read fulfillment, packages and shipment status","security":[{"bearerAuth":["outbound:read"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCode"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Resource not found"}}},"post":{"tags":["Outbound"],"operationId":"submitOutboundOrder","summary":"Submit a draft dropship order and preauthorise its estimated fee","description":"This customer action only submits a draft. Warehouse allocation, picking, packing and shipping remain internal OMS/WMS actions.","security":[{"bearerAuth":["outbound:write"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundOrderSubmit"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for outbound:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/portal/inbound-orders":{"get":{"tags":["Portal","Inbound"],"operationId":"listPortalInboundOrders","summary":"Read customer-safe inbound orders and complete filtered totals","description":"Read-only projection for the customer portal. Requires inbound:read for Bearer/API-cookie credentials; customer password sessions are also supported. Customer and active warehouse scope apply before stable pagination and totals. pageSize defaults to 20. Search matches literal order, reference or tracking text. No internal notes, product snapshots, finance bindings or warehouse workflow actors are returned. Authorization is rechecked before returning; responses are private, no-store.","security":[{"bearerAuth":["inbound:read"]},{"portalSession":[]},{"portalUserSession":[]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/WarehouseCode"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":20}},{"name":"search","in":"query","schema":{"type":"string","maxLength":150}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","submitted","approved","in_transit","arrived","receiving","partially_received","received","partially_putaway","completed","exception","cancelled"]}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"description":"Invalid filter or pagination"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Current customer or warehouse authorization unavailable"}}}},"/portal/inbound-orders/{id}":{"get":{"tags":["Portal","Inbound"],"operationId":"getPortalInboundOrder","summary":"Read receiving quantities, frozen address or printable inbound labels","description":"Returns customerId and order with SKU receipt/putaway quantities, safe carton fields and the saved receiving address. receivedQuantity includes damagedQuantity; good and damaged putaway are separate. Optional label=carton|delivery returns JSON {customerId, orderId, document:{html, labelCount, mode, paper, hash}} instead. Labels use persisted Code128 values, are A4 reference labels (not carrier labels), and never increment physical print counts. Delivery labels require a complete saved address; the current warehouse address is never substituted. Missing/invalid barcodes and cancelled orders reject label generation. Reads are audited, with no warehouse or inventory mutations. This is not a physical-print confirmation or an immutable document-download receipt.","security":[{"bearerAuth":["inbound:read"]},{"portalSession":[]},{"portalUserSession":[]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/WarehouseCode"},{"name":"label","in":"query","schema":{"type":"string","enum":["carton","delivery"]}},{"name":"lang","in":"query","schema":{"type":"string","enum":["ZH","EN"],"default":"ZH"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Current authorization unavailable"},"404":{"description":"Order not found in current scope"},"409":{"description":"Saved address, barcode or order status does not permit labels"}}}},"/portal/inbound-requests":{"get":{"tags":["Portal","Inbound"],"operationId":"listMyInboundRequests","summary":"Recover own inbound requests or read safe order-entry choices","description":"Requires inbound:write. Default: owned pending reminders, or view=history; fixed pages of 20 with pagination.hasMore. action=options returns authorized active warehouses with receiving address/version, settlement accounts and literal-search active products (30 per page). action=edit with orderId returns customer-editable fields and the reviewed draft version; only untouched drafts whose WMS messages have never been claimed or attempted qualify. This is read-only. Current organization, actor, customer, original and target warehouse/account-set scope are rechecked before returning. Responses are private, no-store.","security":[{"bearerAuth":["inbound:write"]},{"portalSession":[]},{"portalUserSession":[]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"name":"view","in":"query","schema":{"type":"string","enum":["pending","history"],"default":"pending"}},{"name":"action","in":"query","schema":{"type":"string","enum":["options","edit"]}},{"name":"orderId","in":"query","schema":{"type":"string","maxLength":100},"description":"Required for action=edit."},{"name":"search","in":"query","schema":{"type":"string","maxLength":150},"description":"Literal SKU or product-name filter for action=options."}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"description":"Invalid query"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Current scope or inbound write permission unavailable"}}},"post":{"tags":["Portal","Inbound"],"operationId":"manageMyInboundRequest","summary":"Prepare, confirm, recover or close a durable inbound request","description":"prepare CREATE stores immutable input without allocating numbers; SUBMIT freezes a reviewed draft version. EDIT freezes replacement customer fields plus a required reason; CANCEL freezes a required reason and draft version. EDIT/CANCEL only allow untouched drafts with no inventory, charges or attempted/claimed WMS delivery. Old unsent WMS messages are atomically retired; EDIT queues a replacement for the current target binding. Same carton numbers retain barcodes; removed labels are obsolete. Same warehouse retains the original address snapshot; selecting a different warehouse freezes its reviewed address. Reuse operationId with identical input after uncertainty. One open request per actor/customer. execute requires confirmed=true and uses only the saved request; exact retries recover its receipt. Outcomes are PENDING, CREATED, SUBMITTED, EDITED or CANCELLED. SUBMITTED means OMS submission, not warehouse acceptance. No receiving, stock, charge, payment or insurance issuance occurs here. acknowledge requires a completed result; archive with a reason only closes the reminder, never cancels the order. Source and target permissions are required. Changed order scope is hidden with orderScopeChanged=true. Cookie writes require double-submit CSRF. Every response is private, no-store.","security":[{"bearerAuth":["inbound:write"]},{"portalSession":[]},{"portalUserSession":[]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"name":"X-TAHO-CSRF","in":"header","required":false,"schema":{"type":"string"},"description":"Required for cookie sessions; must match the portal CSRF cookie and session token hash."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalInboundRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"description":"Invalid input or missing explicit confirmation"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Permission or CSRF check failed"},"404":{"description":"Original request unavailable in current scope"},"409":{"description":"Changed facts, different intent for an existing key, closed request or unresolved reminder"}}}},"/portal/quote-requests":{"get":{"tags":["Pricing"],"operationId":"listMyQuotationReviews","summary":"Recover saved quotation reviews and acceptance receipts","description":"Read-only. Only this principal's currently authorized customer/warehouse requests are returned, with scope filtering before pagination. pending excludes closed reminders; history includes all owned requests. Fixed page size 20. Pass requestId to retrieve immutable customer-facing terms and original acceptance evidence. This never accepts a quotation. Responses are private, no-store.","security":[{"bearerAuth":["pricing:accept"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/Page"},{"name":"requestId","in":"query","schema":{"type":"string","maxLength":100}},{"name":"view","in":"query","schema":{"type":"string","enum":["pending","history"],"default":"pending"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Pricing"],"operationId":"manageMyQuotationReview","summary":"Prepare, explicitly accept, acknowledge or close a durable quotation review","description":"prepare saves the reviewed revision, time and immutable customer-facing rates/terms without accepting. Retry an uncertain prepare with the same operationId and fields. execute uses requestId and confirmed=true; no new quote fields or rates may be supplied. Changed/expired quotations require a new review. Repeated execution resolves original evidence; acknowledge closes a completed reminder, archive requires a reason and only closes the reminder. Neither reverses an accepted quote or creates financial charges. Closed reviews are read-only. Cookie sessions require CSRF. Direct quote acceptance cannot borrow durable IDs or bypass an open review.","security":[{"bearerAuth":["pricing:accept"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalQuoteReviewRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for pricing:accept","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/portal/cancellation-requests":{"get":{"tags":["Outbound"],"operationId":"listMyCancellationRequests","summary":"Read current-principal cancellation intents and immutable outcomes","description":"No business write. Only the authenticated actor's requests within its current customer, warehouse and settlement-book scope are returned. pending excludes acknowledged/archived reminders; history includes all owned requests. Fixed page size 20, pagination.hasMore indicates another page. Every response is private, no-store.","security":[{"bearerAuth":["outbound:write"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/Page"},{"name":"view","in":"query","schema":{"type":"string","enum":["pending","history"],"default":"pending"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Outbound"],"operationId":"manageMyCancellationRequest","summary":"Prepare, confirm, recover or acknowledge a durable cancellation","description":"prepare stores the reviewed order version, reason and fee-hold snapshot without cancelling, releasing or charging. Reuse operationId after an unknown prepare result. execute requires requestId and confirmed=true and must use the saved intent; changed facts return 409. Repeating execute returns the original cancellation receipt. acknowledge closes a completed reminder; archive requires a reason and does not undo a completed cancellation. Cookie sessions require CSRF protection. Amounts are currency minor units; releasedMinor is null until a cancellation receipt exists. Closed requests are read-only.","security":[{"bearerAuth":["outbound:write"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalCancellationRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for outbound:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/outbound-orders/{id}/cancel":{"post":{"tags":["Outbound"],"operationId":"cancelOutboundOrder","summary":"Cancel a pre-fulfilment dropship order and release any fee hold","description":"Only draft, submitted, approved and allocated orders may be cancelled by the customer. Picking, packing and shipping remain internal warehouse actions.","security":[{"bearerAuth":["outbound:write"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundOrderCancel"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for outbound:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pricing/quote":{"post":{"tags":["Pricing"],"operationId":"calculateQuote","summary":"Calculate a quote from the active contract","security":[{"bearerAuth":["pricing:quote"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingQuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for pricing:quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pricing/quotes":{"get":{"tags":["Pricing"],"operationId":"listCustomerQuotes","summary":"List released quotation snapshots including published expired, cancelled and superseded history","security":[{"bearerAuth":["pricing:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/pricing/quotes/{id}":{"get":{"tags":["Pricing"],"operationId":"getCustomerQuote","summary":"Read one quotation snapshot or download its document","description":"Without format, returns the quotation JSON snapshot. Customer-visible billingTerms include normalized minimum charges, rounding and contract surcharge; internal source snapshots and approval comments are omitted. Unreleased drafts return 404. Superseded quotations remain historical evidence, but cannot be selected for new orders. When format is html, xlsx, excel or pdf, returns a versioned document with x-taho-document-audit-id; retrying the same document intent with the same Idempotency-Key returns the same audit id and adds x-taho-document-audit-replayed: 1. format=xlsx returns a native, formula-free XLSX workbook with quotation rates and billing terms. The deprecated format=excel remains Excel-compatible HTML (.xls) for existing clients. PDF requires a configured renderer.","security":[{"bearerAuth":["pricing:read"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/QuoteDocumentFormat"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"$ref":"#/components/responses/QuoteSuccess"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Resource not found"}}},"post":{"tags":["Pricing"],"operationId":"acceptCustomerQuote","summary":"Accept a sent quotation","description":"The response includes immutable acceptance evidence: channel, organization/credential scope, request id, a SHA-256 hash of the accepted quote snapshot, and one-way source fingerprints when the trusted edge supplies them. Raw IP and user-agent values are never persisted.","security":[{"bearerAuth":["pricing:accept"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerQuoteAcceptRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"201":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Business conflict or idempotency fingerprint mismatch for pricing:accept","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/finance/statements":{"get":{"tags":["Finance"],"operationId":"listStatements","summary":"Read issued customer statements and balances","description":"Excludes draft and void statements and applies customer plus settlement-book ownership. The response includes pagination and full-scope currency summaries.","security":[{"bearerAuth":["finance:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/finance/statements/{id}/document":{"get":{"tags":["Finance"],"operationId":"downloadStatementDocument","summary":"Download an issued customer statement","description":"Exports the current issued statement projection and immutable charge evidence; balances and status may change after receipts or credit memos. Draft/void statements are not customer-visible. Native formula-free XLSX includes charges and payment history, using currency minor-unit precision; format=excel is an alias for xlsx and returns a .xlsx file. HTML supports browser printing. PDF requires a configured renderer. Billing dates explicitly use Asia/Shanghai with an exclusive period end. Access and source data are revalidated after rendering. Includes x-taho-document-audit-id; retry the same document intent and bytes with the same Idempotency-Key to reuse the audit event. Changed content or permissions can reject a retry.","security":[{"bearerAuth":["finance:read"]}],"parameters":[{"$ref":"#/components/parameters/Id"},{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/DocumentFormat"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"$ref":"#/components/responses/DocumentSuccess"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Statement not found"}}}},"/finance/wallets":{"get":{"tags":["Finance"],"operationId":"listWallets","summary":"Read prepaid wallet balances by currency","security":[{"bearerAuth":["finance:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/finance/charges":{"get":{"tags":["Finance"],"operationId":"listCharges","summary":"Read immutable customer charge lines","description":"Customer, warehouse and settlement-book ownership filters apply before pagination and currency totals. Unknown or mismatched settlement accounts are excluded until repaired. Returns billing fields only: id, customerId, sourceType, sourceId, sourceNo, warehouseCode, chargeCode, chargeName, category, currency, amountMinor, status, statementId, parentChargeId, occurredAt and createdAt. Internal calculation snapshots, account identifiers, pricing references and approval identities/operation keys are not exposed. Revalidates credentials and ownership before responding; responses are private and no-store. Summaries cover the complete authorized filtered scope, not just the page. Amounts use currency minor units; unsafe aggregate precision returns 409 and requires a narrower date range.","security":[{"bearerAuth":["finance:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Credential or financial scope is unavailable or changed during reading"},"409":{"description":"Financial summary exceeds safe minor-unit precision or scope is too large"}}}},"/portal":{"get":{"tags":["Portal"],"operationId":"getCustomerPortalDashboard","summary":"Read a bounded customer portal dashboard","description":"Statements are issued customer-visible records only, paged 20 at a time using statementPage. statementsPagination returns page, pageSize and total; receivables summaries include the complete authorized scope, not just the current page. Other recent-order and quotation lists remain bounded.","security":[{"bearerAuth":["portal:read"]}],"parameters":[{"$ref":"#/components/parameters/CustomerId"},{"$ref":"#/components/parameters/StatementPage"}],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Customer not found"}}}},"/portal/session":{"post":{"tags":["Portal"],"operationId":"createCustomerPortalSession","summary":"Exchange a customer API credential for an HttpOnly portal session","security":[{"bearerAuth":["portal:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customerId"],"properties":{"customerId":{"type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"get":{"tags":["Portal"],"operationId":"getCustomerPortalSession","summary":"Validate the current customer portal session","security":[],"responses":{"200":{"$ref":"#/components/responses/Success"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"delete":{"tags":["Portal"],"operationId":"revokeCustomerPortalSession","summary":"Revoke the current customer portal session","security":[],"responses":{"204":{"description":"Session revoked"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/portal/auth/password-reset":{"post":{"tags":["Portal"],"operationId":"requestCustomerPortalPasswordReset","summary":"Request a one-time customer portal password reset","description":"Valid same-origin requests receive a generic 202 for active, unknown, disabled or throttled accounts. Eligible requests atomically write an encrypted email outbox event and replace older links. At most one link per account per 60 seconds and five per rolling hour; suppressed requests do not invalidate the current link. A 202 is acknowledgement, not confirmation of email delivery.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalPasswordResetRequest"}}}},"responses":{"202":{"description":"Reset request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"400":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Unauthorized"}}},"put":{"tags":["Portal"],"operationId":"completeCustomerPortalPasswordReset","summary":"Consume a one-time portal password reset token","description":"The token is single-use and expires after 30 minutes. Password validation precedes consumption. Password change, token consumption, revocation of old sessions and pending access links, new HttpOnly session and audit commit atomically. A failed password-policy check leaves the link usable; concurrent completions have only one winner.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalPasswordResetComplete"}}}},"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Unauthorized"},"410":{"description":"Token is invalid, revoked, already used or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"portalSession":{"type":"apiKey","in":"cookie","name":"taho_portal_session","description":"HttpOnly customer session exchanged from an API credential. Reads retain that credential's scope and current authorization."},"portalUserSession":{"type":"apiKey","in":"cookie","name":"taho_portal_session","description":"HttpOnly customer employee session established by portal password login. Shares the cookie name with API-credential sessions; do not send both."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"taho_live_xxx","description":"Use the one-time secret issued for this customer application. The credential is bound to one customer and organization; customerId must match it on every request. OMS stores only a hash and prefix. Configure exact browser Origins in System settings → API configuration when the client is browser-based."}},"parameters":{"Id":{"name":"id","in":"path","required":true,"schema":{"type":"string"}},"CustomerId":{"name":"customerId","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":100},"description":"Customer resource selected by the API credential. It must exactly match the single customer bound to the Bearer credential."},"WarehouseCode":{"name":"warehouseCode","in":"query","required":false,"schema":{"type":"string","maxLength":100},"description":"Optional single warehouse filter. The order detail endpoint accepts at most one value."},"WarehouseCodeList":{"name":"warehouseCode","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":200},"description":"Repeat warehouseCode for multiple warehouses. If omitted, the API applies the complete active warehouse scope linked to the credential organization."},"StatementPage":{"name":"statementPage","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Portal statement page (20 records per page). Invalid or unsafe page values return 400."},"Page":{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},"PageSize":{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},"DocumentFormat":{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["html","excel","xlsx","pdf"]},"description":"Statement document format; the public endpoint defaults to pdf. Both xlsx and excel return native .xlsx, not HTML .xls. PDF requires the configured production renderer."},"QuoteDocumentFormat":{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["html","xlsx","excel","pdf"]},"description":"Quote document: xlsx is native Excel with rates and billing terms; legacy excel is HTML (.xls). PDF requires the configured production renderer."},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":8,"maxLength":150},"description":"Stable per business intent. For document downloads, reuse the same key only for the same customer, document, format and response; a different response returns 409."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"Success":{"type":"object","additionalProperties":true},"WriteRequest":{"type":"object","required":["customerId"],"properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"customerId":{"type":"string","maxLength":100}},"additionalProperties":true},"OperationId":{"type":"string","minLength":8,"maxLength":150,"description":"Stable idempotency key. Use the same value when retrying the same business intent."},"OrderItem":{"type":"object","required":["sku","requestedQuantity"],"properties":{"sku":{"type":"string","maxLength":100},"requestedQuantity":{"type":"integer","minimum":1},"unitPrice":{"type":"number","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"lotNo":{"type":["string","null"],"maxLength":100}}},"InboundOrderItem":{"type":"object","required":["sku","expectedQuantity"],"properties":{"sku":{"type":"string","maxLength":100},"expectedQuantity":{"type":"integer","minimum":1},"cartonNo":{"type":["string","null"],"maxLength":100},"lotNo":{"type":["string","null"],"maxLength":100},"expiryAt":{"type":["number","string","null"],"description":"Expiry as epoch milliseconds or a parseable date."}}},"PortalInboundRequest":{"oneOf":[{"type":"object","required":["action","kind","operationId","order"],"properties":{"action":{"const":"prepare"},"kind":{"const":"CREATE"},"operationId":{"type":"string","minLength":1,"maxLength":100},"order":{"$ref":"#/components/schemas/InboundOrderCreate"}}},{"type":"object","required":["action","kind","operationId","orderId","expectedVersion"],"properties":{"action":{"const":"prepare"},"kind":{"const":"SUBMIT"},"operationId":{"type":"string","minLength":1,"maxLength":100},"orderId":{"type":"string","minLength":1,"maxLength":100},"expectedVersion":{"type":"integer","minimum":1}}},{"type":"object","required":["action","kind","operationId","orderId","expectedVersion","reason","order"],"properties":{"action":{"const":"prepare"},"kind":{"const":"EDIT"},"operationId":{"type":"string","minLength":1,"maxLength":100},"orderId":{"type":"string","minLength":1,"maxLength":100},"expectedVersion":{"type":"integer","minimum":1},"reason":{"type":"string","minLength":1,"maxLength":1000},"order":{"$ref":"#/components/schemas/PortalInboundEdit"}}},{"type":"object","required":["action","kind","operationId","orderId","expectedVersion","reason"],"properties":{"action":{"const":"prepare"},"kind":{"const":"CANCEL"},"operationId":{"type":"string","minLength":1,"maxLength":100},"orderId":{"type":"string","minLength":1,"maxLength":100},"expectedVersion":{"type":"integer","minimum":1},"reason":{"type":"string","minLength":1,"maxLength":1000}}},{"type":"object","required":["action","requestId","confirmed"],"properties":{"action":{"type":"string","enum":["execute","acknowledge"]},"requestId":{"type":"string","minLength":1,"maxLength":100},"confirmed":{"const":true}}},{"type":"object","required":["action","requestId","confirmed","reason"],"properties":{"action":{"const":"archive"},"requestId":{"type":"string","minLength":1,"maxLength":100},"confirmed":{"const":true},"reason":{"type":"string","minLength":1,"maxLength":1000}}}]},"PortalInboundEdit":{"type":"object","additionalProperties":false,"required":["customerId","warehouseCode","expectedWarehouseVersion","items","cartons"],"description":"Full editable draft returned by action=edit. Internal notes, contract bindings, order status, received quantities, barcodes and print counts cannot be changed here. Send all retained items/cartons; omitted lines are removed.","properties":{"customerId":{"type":"string","maxLength":100},"warehouseCode":{"type":"string","maxLength":100},"expectedWarehouseVersion":{"type":"integer","minimum":1},"settlementAccountId":{"type":["string","null"],"maxLength":100},"referenceNo":{"type":["string","null"],"maxLength":150},"shippingMethod":{"type":["string","null"],"maxLength":100},"trackingNo":{"type":["string","null"],"maxLength":150},"expectedAt":{"type":["number","string","null"]},"containerType":{"type":["string","null"],"enum":["20GP","40GP","40HQ","45HQ","40RF",null]},"containerCount":{"type":"integer","minimum":0},"palletCount":{"type":"integer","minimum":0},"declaredCbm":{"type":["number","null"],"minimum":0},"insuranceOptions":{"type":"array","uniqueItems":true,"items":{"enum":["DEAD_STOCK","RETURN","REPAIR"]}},"items":{"type":"array","minItems":1,"maxItems":500,"items":{"$ref":"#/components/schemas/InboundOrderItem"}},"cartons":{"type":"array","maxItems":200,"items":{"type":"object","additionalProperties":false,"required":["cartonNo"],"properties":{"cartonNo":{"type":"string","maxLength":100},"trackingNo":{"type":["string","null"]},"weightGrams":{"type":["number","null"],"minimum":0},"lengthMm":{"type":["number","null"],"minimum":0},"widthMm":{"type":["number","null"],"minimum":0},"heightMm":{"type":["number","null"],"minimum":0}}}}}},"InboundOrderCreate":{"type":"object","required":["customerId","warehouseCode","expectedWarehouseVersion","items"],"properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"customerId":{"type":"string","maxLength":100},"warehouseCode":{"type":"string","maxLength":100},"expectedWarehouseVersion":{"type":"integer","minimum":1},"customerQuoteId":{"type":["string","null"],"maxLength":100,"description":"Optional accepted customer quotation. Its warehouse, route and currency scope is validated by OMS."},"pricingLane":{"type":["string","null"],"maxLength":200,"description":"Frozen pricing route/lane used for billing when no customer quote overrides the same stack group."},"settlementAccountId":{"type":["string","null"],"maxLength":100},"referenceNo":{"type":["string","null"],"maxLength":150},"expectedAt":{"type":["string","null"],"format":"date-time"},"shippingMethod":{"type":["string","null"],"maxLength":100},"trackingNo":{"type":["string","null"],"maxLength":150},"containerType":{"type":["string","null"],"enum":["20GP","40GP","40HQ","45HQ","40RF",null],"description":"Accepted container type for container-based inbound billing. Required when containerCount is positive."},"containerCount":{"type":"integer","minimum":0,"default":0,"description":"Accepted container quantity frozen on the ASN and used by CONTAINER pricing rules."},"palletCount":{"type":"integer","minimum":0,"default":0,"description":"Accepted pallet quantity frozen on the ASN and used by PALLET pricing rules."},"declaredCbm":{"type":["number","null"],"minimum":0,"description":"Accepted business CBM frozen on the ASN and used by CBM pricing rules; do not infer it from unverified carton dimensions."},"insuranceOptions":{"type":"array","items":{"type":"string","enum":["DEAD_STOCK","RETURN","REPAIR"]},"uniqueItems":true},"items":{"type":"array","minItems":1,"maxItems":500,"items":{"$ref":"#/components/schemas/InboundOrderItem"}},"cartons":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"cartonNo":{"type":"string","maxLength":100},"trackingNo":{"type":["string","null"]},"weightGrams":{"type":"number","minimum":0},"lengthMm":{"type":"number","minimum":0},"widthMm":{"type":"number","minimum":0},"heightMm":{"type":"number","minimum":0},"labelData":{"type":["object","null"],"additionalProperties":true}}}},"notes":{"type":["string","null"],"maxLength":5000}}},"OutboundOrderCreate":{"type":"object","required":["customerId","warehouseCode","recipientName","country","city","postalCode","address1","items"],"properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"customerId":{"type":"string","maxLength":100},"warehouseCode":{"type":"string","maxLength":100},"customerQuoteId":{"type":["string","null"],"maxLength":100,"description":"Optional accepted customer quotation used by preauthorisation and final billing."},"pricingLane":{"type":["string","null"],"maxLength":200},"settlementAccountId":{"type":["string","null"],"maxLength":100},"externalOrderId":{"type":["string","null"],"maxLength":150},"referenceNo":{"type":["string","null"],"maxLength":150},"recipientName":{"type":"string","maxLength":200},"recipientCompany":{"type":["string","null"],"maxLength":200},"recipientPhone":{"type":["string","null"],"maxLength":100},"recipientEmail":{"type":["string","null"],"format":"email","maxLength":320},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"state":{"type":["string","null"],"maxLength":200},"city":{"type":"string","maxLength":200},"postalCode":{"type":"string","maxLength":30},"address1":{"type":"string","maxLength":500},"address2":{"type":["string","null"],"maxLength":500},"shippingMethod":{"type":"string","enum":["EXPRESS","TRUCK"],"default":"EXPRESS"},"labelSource":{"type":"string","enum":["CUSTOMER","WAREHOUSE"],"default":"WAREHOUSE"},"serviceCode":{"type":["string","null"],"maxLength":100},"insuranceOptions":{"type":"array","items":{"type":"string","enum":["DEAD_STOCK","RETURN","REPAIR"]},"uniqueItems":true},"items":{"type":"array","minItems":1,"maxItems":500,"items":{"$ref":"#/components/schemas/OrderItem"}},"packages":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":true}},"notes":{"type":["string","null"],"maxLength":5000}}},"OutboundOrderSubmit":{"type":"object","required":["customerId"],"properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"customerId":{"type":"string","maxLength":100},"expectedVersion":{"type":["integer","null"],"minimum":1,"description":"Optional optimistic-concurrency version from the last order read."}}},"PortalQuoteReviewRequest":{"oneOf":[{"type":"object","required":["action","operationId","quoteId","expectedRevisionNo","expectedUpdatedAt"],"properties":{"action":{"const":"prepare"},"operationId":{"type":"string","minLength":1,"maxLength":100},"quoteId":{"type":"string","minLength":1,"maxLength":100},"expectedRevisionNo":{"type":"integer","minimum":1},"expectedUpdatedAt":{"type":"integer","minimum":1},"comment":{"type":["string","null"],"maxLength":2000}}},{"type":"object","required":["action","requestId","confirmed"],"properties":{"action":{"type":"string","enum":["execute","acknowledge"]},"requestId":{"type":"string","maxLength":100},"confirmed":{"const":true}}},{"type":"object","required":["action","requestId","confirmed","reason"],"properties":{"action":{"const":"archive"},"requestId":{"type":"string","maxLength":100},"confirmed":{"const":true},"reason":{"type":"string","minLength":1,"maxLength":1000}}}]},"PortalCancellationRequest":{"oneOf":[{"type":"object","required":["action","operationId","orderId","expectedVersion","reason"],"properties":{"action":{"const":"prepare"},"operationId":{"type":"string","minLength":1,"maxLength":100},"orderId":{"type":"string","minLength":1,"maxLength":100},"expectedVersion":{"type":"integer","minimum":1},"reason":{"type":"string","minLength":1,"maxLength":500}}},{"type":"object","required":["action","requestId","confirmed"],"properties":{"action":{"type":"string","enum":["execute","acknowledge"]},"requestId":{"type":"string","maxLength":100},"confirmed":{"const":true}}},{"type":"object","required":["action","requestId","confirmed","reason"],"properties":{"action":{"const":"archive"},"requestId":{"type":"string","maxLength":100},"confirmed":{"const":true},"reason":{"type":"string","minLength":1,"maxLength":1000}}}]},"OutboundOrderCancel":{"type":"object","required":["customerId","expectedVersion"],"properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"customerId":{"type":"string","maxLength":100},"expectedVersion":{"type":"integer","minimum":1,"description":"Required version from the reviewed order. Retry an unknown result with the same operationId, version and reason; the original cancellation receipt is returned without releasing twice."},"reason":{"type":["string","null"],"maxLength":500,"description":"Optional operator/customer reason retained in the immutable workflow event."}},"additionalProperties":false},"PricingQuoteRequest":{"type":"object","required":["input"],"properties":{"templateId":{"type":["string","null"],"description":"Optional active template. If omitted OMS selects the best customer/warehouse/route match."},"input":{"type":"object","required":["customerId"],"additionalProperties":true,"description":"Pricing facts such as mode, route, weight, cartons, pallets, CBM or containers."}}},"CustomerQuoteAcceptRequest":{"type":"object","required":["operationId","confirmed","expectedRevisionNo","expectedUpdatedAt"],"description":"Explicitly accept the version reviewed by the customer. Reuse the same operationId and reviewed fields after an uncertain response. A changed quotation or revoked authorization is rejected; confirmation never edits template rates.","properties":{"operationId":{"$ref":"#/components/schemas/OperationId"},"confirmed":{"const":true},"expectedRevisionNo":{"type":"integer","minimum":1},"expectedUpdatedAt":{"type":"integer","minimum":1},"action":{"const":"ACCEPT"},"comment":{"type":["string","null"],"maxLength":2000}}},"PortalPasswordResetRequest":{"type":"object","required":["customerId","email"],"properties":{"customerId":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","format":"email","maxLength":254}},"additionalProperties":false},"PortalPasswordResetComplete":{"type":"object","required":["token","password"],"properties":{"token":{"type":"string","minLength":1,"maxLength":300},"password":{"type":"string","minLength":10,"maxLength":200}},"additionalProperties":false}},"responses":{"Success":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"QuoteSuccess":{"description":"Quotation JSON snapshot or immutable customer document","headers":{"x-taho-document-audit-id":{"$ref":"#/components/headers/DocumentAuditId"},"x-taho-document-audit-replayed":{"$ref":"#/components/headers/DocumentAuditReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}},"text/html":{"schema":{"type":"string"}},"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/vnd.ms-excel":{"schema":{"type":"string","format":"binary"}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}}}},"DocumentSuccess":{"description":"Immutable customer document","headers":{"x-taho-document-audit-id":{"$ref":"#/components/headers/DocumentAuditId"},"x-taho-document-audit-replayed":{"$ref":"#/components/headers/DocumentAuditReplayed"}},"content":{"text/html":{"schema":{"type":"string"}},"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/vnd.ms-excel":{"schema":{"type":"string","format":"binary"}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}}}},"Unauthorized":{"description":"Missing, invalid or inactive API credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"headers":{"DocumentAuditId":{"description":"Immutable audit event ID for this document response. Persist it with the downloaded file or downstream accounting reference.","schema":{"type":"string","minLength":1}},"DocumentAuditReplayed":{"description":"Present with value 1 when the Idempotency-Key replayed an existing public document access event.","schema":{"type":"string","enum":["1"]}}}}}