Orders
An OTA Channel Manager order represents a single purchase made by an external sales channel. The
order header carries the partner and customer context; one or more item lines describe what is being
issued. The endpoints are asynchronous — createOrder and replaceOrder accept the
order, persist it as Submitted, and return immediately. Ticket and coupon issuance, wallet
manifest build, and settling to a terminal state all happen in the background.
External reference numbers
If you need a stable, customer-facing identifier for each wallet at the moment you receive a
Submitted response — to render as a QR code in a confirmation email, print on a receipt, or store
in your own system as the customer’s “ticket number” — supply it yourself when you submit the order.
Set wallet.externalReferenceNumbers to an array containing one value per expected wallet on the
line (quantity values for individual tickets, or 1 for group tickets). On submission your values
are stored on the wallet shells and echoed back in the response. When the wallets are later minted,
the same numbers are stamped onto them — so the reference you handed your customer at submit time
is exactly what they will present at admission.
Key concepts
- Partner identity —
partnerIdidentifies your integration. It is issued when your partnership is set up; orders submitted before then, or under a partnership that has been disabled, are rejected. - Order references —
sellToOrderReferenceis the partner’s own order number. The pair(partnerId, sellToOrderReference)is unique per order; this lets partners look up an order by their own reference and protects against duplicate submission.buyFromOrderReferenceis the OTA Channel Manager’s own document number, returned in every response for partner-side reconciliation. - Items — each
itemsentry resolves to one configured item. The line’squantity,visitDate, andvisitTimeapply to all wallets that the line issues. A package item additionally expands into one wallet per package, with component-level scheduling provided viawallet.componentSchedule. Some packages also yield discount coupons alongside the tickets. - Wallets and assets — issued tickets and coupons live inside a wallet, which is the unit of
issuance (one wallet per recipient). The response carries the wallet’s
walletReferenceNumber, the individual asset numbers underassets(each entry is either aticketor acoupon), and amanifestUrlfor rendering the wallet. The partner is responsible for delivering the wallet (or itsmanifestUrl) to the customer.
Status lifecycle
replaceOrder is rejected outside Draft and Error. deleteOrder is rejected while the order
is Submitted, Scheduled, or Processing; wait for the order to settle to a terminal status and
retry.
Status semantics
Submitted/Scheduled/Processingare the in-flight states. From a partner’s point of view they are equivalent — “the order is still being worked on.” Subscribe toota_cm_order_processedfor completion notifications, or pollgetOrder.Draftis the resting state for orders that completed issuance without apaymentReference. Tickets and coupons have been minted but are not valid until the order is confirmed. SendpaymentReferenceviaconfirmOrderto release them toIssued.Issuedis the normal terminal state once tickets and coupons have been minted and the manifest built.Errororders expose the failure reason instatusMessage. The recommended remediation is to fix the offending item or schedule and callreplaceOrder(which destroys any partial wallets and re-issues), or to delete the order outright.
Replacing versus deleting
PUT /channelManager/{orderId} replaces the contents of an order — header mutables, items,
wallets — but not its identity. To cancel an issued order, call DELETE; the row is retained with
status = Cancelled for audit, and the wallets are destroyed. Deleting a Draft or Error order
removes the order row entirely.
Idempotency notes
createOrderis idempotent on(partnerId, sellToOrderReference)only in the sense that a second submission is rejected with400 Bad Request. There is no automatic merge — to retry after an error, usereplaceOrder.confirmOrderon an already-Issuedorder is a no-op and returns the order unchanged.
