Return webhooks cover two distinct encrypted flows:
- A customer sends an encrypted return request to the original issuer (
RETURN_REQUESTED). - An issuer creates a credit note through the device-generation flow, and an elected owner device encrypts the generated document bundle for downstream recipients (
CREDIT_NOTE_CREATED).
The backend routes both ciphertext types without decrypting them.
{
"name": "Returns integration",
"notificationUrl": "https://your-domain.example/webhooks/cheqi",
"events": [
"RETURN_REQUESTED",
"CREDIT_NOTE_CREATED"
]
}{
"event": "RETURN_REQUESTED",
"data": {
"creditNoteInitiationRequest": {
"clientId": "issuer-public-client-id",
"companyId": "550e8400-e29b-41d4-a716-446655440000",
"userId": "8ccf09a7-d969-4a09-880f-42d520a0999a",
"created_at": "2026-08-03T14:00:00Z",
"cheqiReceiptId": "CHQ-20260803-ABC123",
"publicKey": "base64-issuer-public-key...",
"encryptedCreditNoteInitiationRequest": "base64-ciphertext...",
"encryptedSymmetricKey": "base64-wrapped-aes-key..."
}
}
}The customer device created this encrypted request for the original receipt issuer. Unwrap encryptedSymmetricKey, decrypt encryptedCreditNoteInitiationRequest, and deserialize the plaintext as CreditNoteInitiationRequest.
The plaintext contract contains:
cheqiReceiptId: Cheqi identifier of the original receipt.receiptId: issuer-supplied identifier of the original receipt.customerNote: optional customer note.lineItems: requested quantities and return reasons.refundPreference: preferred refund method.refundBankAccount: supplied only when required for a bank-transfer preference.
This request is not a credit note and is not a ReceiptEnvelope. Validate it against your records and return policy before issuing a credit note.
When accepting a return, issue the credit note through POST /credit-note/encrypted:
- Resolve the original owner's current devices.
- Encrypt the credit-note generation input independently for every returned device recipient.
- Submit the encrypted generation request with
parentCheqiReceiptId. - Owner devices generate and store their local CHEQI credit note.
- One elected device builds and encrypts downstream
ReceiptEnvelopebundles. - Cheqi sends
CREDIT_NOTE_CREATEDafter those encrypted deliveries are accepted.
Do not use the legacy EncryptedCreditNoteDto delivery shape. It is not part of the current webhook contract.
{
"event": "CREDIT_NOTE_CREATED",
"data": {
"encryptedCreditNote": {
"clientId": "your-public-client-id",
"companyId": "550e8400-e29b-41d4-a716-446655440000",
"created_at": "2026-08-03T15:00:00Z",
"cheqiReceiptId": "CHQ-CN-20260803-DEF456",
"encryptedEnvelope": "base64-ciphertext...",
"encryptedEnvelopeKey": "base64-wrapped-aes-key...",
"publicKey": "base64-recipient-public-key-snapshot...",
"recipientKeyAlgorithm": "RSA_2048",
"envelopeVersion": 1,
"receiptGeneratorVersion": "0.3.0",
"finalHash": "sha256-cheqi-credit-note-hash..."
}
}
}Decrypt encryptedEnvelope with the same SDK envelope implementation used for receipt webhooks. The plaintext is a ReceiptEnvelope whose documents map contains:
CHEQIalways.UBL_CREDIT_NOTEwhen required by the recipient's accepted formats.
The documents map is authoritative. There is no separate format list or customer-details ciphertext.
finalHash is the definitive CHEQI credit-note hash submitted by the elected device together with the encrypted deliveries. A separate finalization event is not required.
- Verify
X-Cheqi-Signatureusing the exact raw request body. - Persist the event before returning
2xx. - Process asynchronously and idempotently.
- Keep historical private keys available for deliveries encrypted before a key rotation.
- Never log decrypted return requests, document envelopes, or unwrapped AES keys.
See Webhook Events for the shared event contract and Webhook Security for signature verification.