After validating a customer return, calculate the accepted credit from your authoritative transaction data and submit a definitive credit-note generation input. The SDK resolves the original receipt's owner devices, encrypts the same input independently for each device, and submits it through the credit-note endpoint.
Your system owns eligibility, accepted quantity, financial and tax calculations, payment processing, reconciliation, and customer communication. The SDK serializes the values you provide without recalculating them.
Supply positive quantities and positive credit amounts. A credit note represents the reversal through its document type; negative quantities or totals are not required and produce incorrect UBL semantics for the current generator.
For example, a full credit of a €100.00 net line with 21% VAT uses:
quantity:1subtotal:100.00totalTaxAmount:21.00totalAmount:121.00
The plaintext encrypted for each owner device has two top-level properties:
| Property | Type | Required | Description |
|---|---|---|---|
creditNoteTemplateRequest | object | Yes | Definitive merchant-supplied credit-note values. |
taxesApplied | boolean | Yes | Set to false when no tax applies; otherwise provide tax entries with values. |
{
"creditNoteTemplateRequest": {
"documentNumber": "CN-2026-0042",
"originatorDocumentReference": "INV-2026-0042",
"identifiers": [
{ "type": "RETURN_AUTHORIZATION", "value": "RMA-91827" }
],
"issueDate": "2026-08-05T14:30:22Z",
"currency": "EUR",
"creditNoteSubtotal": 100.00,
"totalBeforeTax": 100.00,
"totalTaxAmount": 21.00,
"totalAmount": 121.00,
"products": [
{
"identifier": "SKU-AIRMAX-BLK-42",
"brandName": "Nike",
"name": "AirMax",
"quantity": 1,
"baseQuantity": 1,
"unitCode": "C62",
"unitPrice": 100.00,
"subtotal": 100.00,
"total": 121.00,
"taxes": [
{
"rate": 21,
"type": "VAT",
"taxableAmount": 100.00,
"amount": 21.00,
"category": "STANDARD"
}
]
}
],
"taxes": [
{
"rate": 21,
"type": "VAT",
"taxableAmount": 100.00,
"amount": 21.00,
"label": "VAT 21%",
"category": "STANDARD"
}
]
},
"taxesApplied": true
}C62 is the UN/ECE unit code for one item. Use the unit and tax category appropriate to the original transaction.
| Property | Description |
|---|---|
documentNumber | Your unique credit-note number. |
originatorDocumentReference | Your document number for the original receipt. |
issueDate | ISO 8601 issue date and time. |
currency | ISO 4217 code. |
creditNoteSubtotal | Line subtotal before document-level adjustments and tax. |
totalBeforeTax | Total after document-level adjustments, excluding tax. |
totalTaxAmount | Total tax credit. |
totalAmount | Tax-inclusive total credit. |
products | At least one credited product. |
Every product needs name, identifier, quantity, unitCode, unitPrice, subtotal, and total. The identifier should match the return request's productId and the original receipt product's identifier.
When taxesApplied is true, include document-level tax entries and the relevant product-level entries. Each tax needs rate, type, and taxableAmount; include amount for the calculated tax credit. When tax does not apply, set taxesApplied to false and the tax arrays may be empty.
Optional document properties are identifiers, discounts, charges, period, and jurisdictionalData. The legacy note property is ignored by the current document generator; configure the company's receipt text when a seller note should appear.
See Credit Notes for the full property summary.
Use request.productId and the parent receipt identifiers to look up the original line in your own system. Do not trust prices or derive refund eligibility from customer input.
function buildCreditNoteGenerationInput(returnRequest, originalReceipt) {
const acceptedLines = validateAndPriceReturn(returnRequest, originalReceipt);
const products = acceptedLines.map(({ originalLine, acceptedQuantity }) => {
const subtotal = calculateNetCredit(originalLine, acceptedQuantity);
const tax = calculateTaxCredit(originalLine, acceptedQuantity);
return {
identifier: originalLine.identifier,
brandName: originalLine.brandName,
name: originalLine.name,
quantity: acceptedQuantity,
baseQuantity: originalLine.baseQuantity ?? 1,
unitCode: originalLine.unitCode,
unitPrice: originalLine.unitPrice,
subtotal,
total: subtotal + tax,
taxes: [{
rate: originalLine.taxRate,
type: originalLine.taxType,
taxableAmount: subtotal,
amount: tax,
category: originalLine.taxCategory
}]
};
});
const totalBeforeTax = products.reduce((sum, line) => sum + line.subtotal, 0);
const totalTaxAmount = products.reduce(
(sum, line) => sum + line.taxes.reduce((taxSum, tax) => taxSum + tax.amount, 0),
0
);
return {
creditNoteTemplateRequest: {
documentNumber: generateCreditNoteNumber(),
originatorDocumentReference: returnRequest.receiptId,
issueDate: new Date().toISOString(),
currency: originalReceipt.currency,
creditNoteSubtotal: totalBeforeTax,
totalBeforeTax,
totalTaxAmount,
totalAmount: totalBeforeTax + totalTaxAmount,
products,
taxes: aggregateTaxes(products)
},
taxesApplied: originalReceipt.taxesApplied
};
}Use decimal-safe arithmetic in production; the example leaves those business-specific functions to your implementation.
Identify the recipient through the parent cheqiReceiptId, then pass that same ID separately as parentCheqiReceiptId:
const parentCheqiReceiptId = returnRequest.cheqiReceiptId;
const identification = { cheqiReceiptId: parentCheqiReceiptId };
const generationInput = buildCreditNoteGenerationInput(
returnRequest,
originalReceipt
);
const result = await sdk.creditNoteService.issueCreditNote(
identification,
parentCheqiReceiptId,
generationInput
);
if (result.isAccepted()) {
console.log("Credit note accepted", result.cheqiReceiptId);
}For OAuth, pass the access token as the fourth argument. To specify a store and OAuth token, pass storeId as the fourth argument and the token as the fifth.
The current Java method accepts the generation input as an object while the public typed schema is being finalized:
Map<String, Object> generationInput = Map.of(
"creditNoteTemplateRequest", creditNoteTemplateRequest,
"taxesApplied", taxesApplied
);
IdentificationDetails identification = new IdentificationDetails()
.cheqiReceiptId(returnRequest.getCheqiReceiptId());
CreditNoteResult result = sdk.getCreditNoteService().issueCreditNote(
identification,
returnRequest.getCheqiReceiptId(),
generationInput
);
if (result.isAccepted()) {
log.info("Credit note accepted: {}", result.getCheqiReceiptId());
}The OAuth overload takes accessToken after the generation input. An overload with storeId and accessToken is also available.
An accepted SDK result contains:
| Property | Description |
|---|---|
cheqiReceiptId | Identifier assigned to the new credit-note generation job/document. |
parentCheqiReceiptId | Original receipt ID supplied by the merchant. |
matchId | Recipient-resolution match identifier. |
status | Initial submission status. |
createdAt | Submission timestamp. |
Acceptance means the encrypted generation job was queued; it does not mean a payment refund has been completed. Update the original return request's status separately using its requestId, and only mark it COMPLETED when your return workflow has actually finished.