Skip to content

Use the SDK-level complete-receipt flow where available. It coordinates the merchant side of the current digital route:

  1. resolve the customer and owner devices
  2. inspect the explicit deliveryRouteType
  3. serialize the definitive receipt payload locally
  4. encrypt that payload independently for every matched device
  5. submit the complete device set to /receipt/encrypted

The accepted submission becomes durable device work. Final CHEQI and UBL documents are generated later on owner devices, not by the backend.

Complete receipt flow

ReceiptResult result = sdk.getReceiptService()
    .issueReceipt(identificationDetails, receiptPayload);

if (result.isAccepted()) {
    System.out.println(result.getDeliveryRouteType());
    System.out.println(result.getCheqiReceiptId());
} else if (result.isEmailReceiptRequired()) {
    // Generate and submit the email receipt explicitly.
} else if (result.isDownloadEnvelopeRequired()) {
    // Build a final ReceiptEnvelope and call completeDownloadFallback(...).
}

Both current SDKs accept a definitive ReceiptPayload. For digital delivery, the SDK encrypts that input locally; it does not send it to a plaintext template-generation endpoint. A missing route is raised as CUSTOMER_NOT_FOUND by the high-level method rather than returned as a ReceiptResult state.

Low-level encrypted submission

If you implement the low-level flow yourself, submit the match and one independently encrypted copy per matched device:

{
  "matchId": "match_opaque",
  "storeId": "4ce2f858-d57d-4fde-a7ce-2e93f165494b",
  "deviceDeliveries": [
    {
      "deviceRecipientId": "rcpt_temporary_1",
      "encryptedContent": "base64-aes-gcm-ciphertext",
      "encryptedAesKey": "base64-wrapped-content-key"
    },
    {
      "deviceRecipientId": "rcpt_temporary_2",
      "encryptedContent": "base64-aes-gcm-ciphertext",
      "encryptedAesKey": "base64-wrapped-content-key"
    }
  ]
}

storeId is optional. When present, it must identify a store directly owned by the company in the authenticated token. The authenticated company remains the legal issuer.

A successful request returns 202 Accepted:

{
  "cheqiReceiptId": "CHQ-20260802-143502-A1B2C3",
  "matchId": "match_opaque",
  "status": "PENDING",
  "createdAt": "2026-08-02T14:35:02Z"
}

Acceptance means Cheqi durably queued the encrypted work. It does not mean a phone has generated or acknowledged the receipt yet.

Submission rules

  • Treat matchId as single-use, short-lived flow state.
  • Submit exactly the temporary device recipient IDs returned by that match.
  • Encrypt the same definitive payload independently with a fresh symmetric key for every device.
  • Preserve the returned cheqiReceiptId; it identifies the durable receipt job after the match has been consumed.
  • A retry with the same match and identical request is idempotent. A conflicting replay is rejected.
  • Do not put plaintext receipt contents, final CHEQI JSON, or UBL XML in the encrypted-submission request outside the device ciphertext.

Determine the legal issuer before recipient resolution and use the same company-bound access token through resolution and encrypted submission.

For company groups, obtain a delegated token for the company that legally made the sale. A parent-company token cannot select a child as issuer. The deprecated childCompanyId field does not grant parent-to-child issuance.

See Companies, Child Companies, and Stores for retail, group, and franchise mappings.

Delivery routes

Follow deliveryRouteType; do not infer the route from recipient count.

  • DIGITAL: encrypt the definitive payload for every matched owner device and submit /receipt/encrypted.
  • DOWNLOAD_FALLBACK: build and encrypt the download envelope locally, then use /receipt/download. The response URL carries the content key only in its fragment.
  • routeFound: false: stop with customer-not-found in the healthy online flow.

Download fallback does not return a Cheqi-held recipient key and does not go through /receipt/encrypted. See Download Links.

After submission

Cheqi creates durable encrypted generation work for each assigned device and an outbox entry for its opaque push hint. A phone may process the job from that hint or during foreground catch-up sync. Only device generation, acknowledgement, and encrypted downstream delivery advance the durable job; provider acceptance of a push does not.

See Mobile Delivery for APNs, FCM, notification permission, retry, and force-quit behavior.