{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Receipt Webhooks","description":"Complete documentation for integrating Cheqi's digital receipt platform","keywords":["cheqi","digital receipts","api","sdk","java","javascript"],"llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"receipt-webhooks","__idx":0},"children":["Receipt Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Receipt webhooks deliver encrypted, recipient-specific document bundles and their definitive CHEQI hash to authorized integrations."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"subscribe","__idx":1},"children":["Subscribe"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"Receipt integration\",\n  \"notificationUrl\": \"https://your-domain.example/webhooks/cheqi\",\n  \"events\": [\"RECEIPT_CREATED\"]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/webhooks/setup"},"children":["Webhook Setup"]}," for registration and ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/webhooks/security"},"children":["Webhook Security"]}," for signature verification."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"receipt-created-flow","__idx":2},"children":["Receipt-created flow"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A merchant submits receipt-generation input encrypted independently for the matched owner devices."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Each owner device decrypts its job and generates its local CHEQI receipt with the shared Rust engine."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["One leased device resolves current downstream recipients."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That device builds a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ReceiptEnvelope"]}," for each recipient and encrypts it using that recipient's key."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Cheqi stores and routes the ciphertext without decrypting it."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Cheqi sends ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIPT_CREATED"]}," to the subscribed receiving integration."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"receipt_created","__idx":3},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIPT_CREATED"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"RECEIPT_CREATED\",\n  \"data\": {\n    \"encryptedReceipt\": {\n      \"clientId\": \"your-public-client-id\",\n      \"companyId\": \"550e8400-e29b-41d4-a716-446655440000\",\n      \"created_at\": \"2026-08-03T13:30:00Z\",\n      \"cheqiReceiptId\": \"CHQ-20260803-ABC123\",\n      \"encryptedEnvelope\": \"base64-ciphertext...\",\n      \"encryptedEnvelopeKey\": \"base64-wrapped-aes-key...\",\n      \"publicKey\": \"base64-recipient-public-key-snapshot...\",\n      \"recipientKeyAlgorithm\": \"RSA_2048\",\n      \"envelopeVersion\": 1,\n      \"receiptGeneratorVersion\": \"0.3.0\",\n      \"finalHash\": \"sha256-cheqi-document-hash...\"\n    }\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["finalHash"]}," is the definitive CHEQI document hash submitted by the elected device together with the encrypted deliveries. A separate finalization event is not required."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ciphertext and wrapped key are the values originally submitted by the elected owner device. Cheqi does not decrypt, rebuild, or merge the receipt documents."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"decrypt-into-receiptenvelope","__idx":4},"children":["Decrypt into ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ReceiptEnvelope"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After unwrapping the AES key and decrypting ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["encryptedEnvelope"]},", deserialize the plaintext JSON into ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ReceiptEnvelope"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public record ReceiptEnvelope(\n        int envelopeVersion,\n        UUID receiptUuid,\n        String cheqiReceiptId,\n        String receiptGeneratorVersion,\n        Map<String, ReceiptEnvelopeDocument> documents\n) {}\n\npublic record ReceiptEnvelopeDocument(\n        String mediaType,\n        String content\n) {}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example processing logic:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"WebhookPayload receipt = event.data().encryptedReceipt();\n\nbyte[] plaintext = envelopeCrypto.decrypt(\n        receipt.encryptedEnvelope(),\n        receipt.encryptedEnvelopeKey(),\n        receipt.publicKey(),\n        receipt.recipientKeyAlgorithm()\n);\n\nReceiptEnvelope envelope = objectMapper.readValue(\n        plaintext,\n        ReceiptEnvelope.class\n);\n\nReceiptEnvelopeDocument cheqi = envelope.documents().get(\"CHEQI\");\nReceiptEnvelopeDocument invoice = envelope.documents().get(\"UBL_INVOICE\");\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the SDK's envelope crypto implementation rather than inventing a separate wire format. The public-key snapshot lets an integration with rotated keys select the historical private key used for this delivery."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Documents determine formats"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Inspect ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ReceiptEnvelope.documents"]}," to determine what was delivered. The webhook does not include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["receiptFormats"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["encryptedCustomerDetails"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["encryptedCustomerAesKey"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"handler-outline","__idx":5},"children":["Handler outline"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify the signature using the exact raw body before parsing it:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"public ResponseEntity<Void> receive(String rawBody, String signature) {\n    if (!signatureVerifier.isValid(rawBody, signature)) {\n        return ResponseEntity.status(401).build();\n    }\n\n    WebhookEvent event = objectMapper.readValue(rawBody, WebhookEvent.class);\n    webhookQueue.enqueue(event);\n    return ResponseEntity.ok().build();\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the asynchronous worker, route ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIPT_CREATED"]}," to the envelope-decryption and reconciliation path. Store events idempotently because delivery can be retried."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For the complete event schemas, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/webhooks/events"},"children":["Webhook Events"]},"."]}]},"headings":[{"value":"Receipt Webhooks","id":"receipt-webhooks","depth":1},{"value":"Subscribe","id":"subscribe","depth":2},{"value":"Receipt-created flow","id":"receipt-created-flow","depth":2},{"value":"RECEIPT_CREATED","id":"receipt_created","depth":2},{"value":"Decrypt into ReceiptEnvelope","id":"decrypt-into-receiptenvelope","depth":3},{"value":"Handler outline","id":"handler-outline","depth":2}],"frontmatter":{"seo":{"title":"Receipt Webhooks"}},"lastModified":"2026-08-03T14:15:03.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/webhooks/receipt-webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}