Submit a sale for loyalty processing. Send at least one item: omitted, null or empty items are rejected by the business validator even though the input model permits them. customer.id and customer.name are required input fields. Resolve the registered customer first: customer.id must be the Kivly ID returned by the customer lookup; an external ID belongs in customer.external_id (or external_customer_id). Matching tries external ID, then phone, then Kivly customer ID. Email alone is not used to match the invoice's customer. This endpoint does not register an unknown customer. Monetary totals (total, subtotal, discount) and item prices are integer minor units (1250 = EUR 12.50). Use a stable, unique code for each sale. Existing codes are detected on sequential retries, but this route does not provide a general exactly-once transaction guarantee. Do not retry ambiguous timeouts or send the same sale concurrently without reconciling its result. The operation processes loyalty before responding; a 200 business response can still have success=false. Accepted responses include points_earned and available_balance in the business's raw loyalty units (points, money minor units or visits). An already processed sale returns duplicate=true and points_earned=0. Rewards are handled before the duplicate transaction check, so duplicate detection does not guarantee that replaying promotions is side-effect free. total.tax is an integer VAT percentage, not a monetary amount. This is a loyalty sale operation, not fiscal invoice issuance.
Integration access is restricted to the credential's location. Pagination, monetary units and response envelopes are endpoint-specific; use the schema below. Do not assume that POST/PATCH requests are safe to retry after a timeout.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
