Write a sale — lines, what was collected, what is left owing
POST/api/contacts/:contact/crm/order
The three parts travel together because their api takes them together: one atomic call writes the lines, the cash taken and the deferred rows. Splitting them here would invent a half-written receipt their system has no state for.
A receipt that does not balance is refused by name
(crm_write_totals_do_not_balance), per currency — and the missing row
is never invented. A panel that quietly added a debt line would be
asserting that a patient owes money.
reference is the duplicate defence, and only the caller can make it work
A sale cannot use the appointment's "same instant, same person" test: two
identical sales in one day are ordinary, and adopting the second would
silently lose a charge. So the caller supplies a token, it is written to
trackingNumber, and the adapter matches it exactly on read-back.
Send the SAME token when retrying. A fresh token per attempt makes
the defence do nothing — which is why this endpoint takes one rather than
generating it: a server-side token would be new on every call and would
look like protection while providing none. Without it, the response says
adoption_checked: false rather than implying a check that did not run.
Request
Responses
- 201
- 409
- 422
- 503
Written; the refreshed card and the write receipt.
crm_not_connected · crm_write_closed · crm_not_linked · crm_ambiguous_link.
crm_write_totals_do_not_balance when the parts disagree, or
crm_invalid_draft when the draft could never be a sale.
Their server did not answer; nothing was written.