Refund Webhook
1. Background
After the partner submits a cashin refund request, the refund result may not be determinable within the synchronous request. Once the refund succeeds or fails, Adopay notifies the partner of the final refund result via an HTTP asynchronous callback.
The same refund order may be notified multiple times due to retries.
2. Callback Endpoint and Method
| Item | Value |
|---|---|
| Method | POST |
| URL | {cashinRefundNotificationUrl} |
| Content-Type | application/json |
| Purpose | Notify the final cashin refund result |
{cashinRefundNotificationUrl} uses the notifyUrl the partner submitted when initiating the refund; if none was submitted, it uses the partner's configured and enabled refund notification URL. The callback URL must be a complete HTTP or HTTPS URL.
3. Request Headers
| Field | Type | Required | Description |
|---|---|---|---|
Content-Type | string | Yes | Fixed to application/json. |
X-Merchant-Id | string | Yes | Primary merchant ID that receives the notification. |
X-Timestamp | string | Yes | Unix timestamp in seconds. |
X-Nonce | string | Yes | Random string for this request, used for anti-replay; regenerated on every retry. |
Digest | string | Yes | Digest of the raw request body, in the format SHA-256=<Base64(SHA256(body_bytes))>. |
Authorization | string | Yes | ES256 HTTP Signature information. |
Both Digest and Authorization are computed over the raw JSON bytes actually sent. When verifying the signature, the partner must not re-serialize the JSON first.
4. Request Body Fields
Business status: status is an integer; status = 200 means the business call succeeded, in which case msg = "sucesso". Any value other than 200 indicates a business error; see msg for the reason.
| Field | Type | Length | Returned | Description |
|---|---|---|---|---|
event | string | 32 | Yes | Refund event type; the value depends on the refund result. See the refund events and statuses below. |
subMerchantNo | string | 64 | Yes | Sub-merchant ID. |
attach | string | 128 | Yes | attach value the partner submitted when placing the original payment order; returned as-is if it was submitted, empty otherwise. |
merchantOrderNo | string | 64 | Yes | Merchant refund order number the partner submitted when initiating the refund. |
platOrderNo | string | 64 | Yes | Adopay platform refund order number. |
origMerchantOrderNo | string | 64 | Yes | Original merchant cashin order number. |
origPlatOrderNo | string | 64 | Yes | Original Adopay cashin platform order number. |
origAmount | decimal(25,2) | 25,2 | Yes | Original cashin order amount. |
origTotalRefundAmount | decimal(25,2) | 25,2 | Yes | As of the completion of this refund, the accumulated principal successfully refunded for the original cashin order, excluding fees. |
origTotalFeeRefundAmount | decimal(25,2) | 25,2 | Yes | As of the completion of this refund, the accumulated fees successfully refunded for the original cashin order, excluding the refund principal. |
amount | decimal(25,2) | 25,2 | Yes | Principal amount requested for refund in this request, excluding the fee. |
refundAmount | decimal(25,2) | 25,2 | Yes | Principal amount successfully refunded in this request, excluding the fee; for the fee refunded, see feeRefundAmount. |
feeRefundAmount | decimal(25,2) | 25,2 | Yes | Fee amount refunded in this refund; 0 when no fee is refunded. |
currency | string | 3 | Yes | Refund currency, identical to the original order's currency, for example BRL. |
e2eId | string | 64 | No | PIX end-to-end transaction ID; may be empty when the channel has not returned it. |
orderStatus | string | 16 | Yes | Refund result: SUCCESS means the refund succeeded, FAILED means the refund failed. |
refundTime | int | 19 | No | Refund time, Unix timestamp in seconds. |
status | int | - | Yes | Response code |
msg | string | 128 | Yes | Message corresponding to status |
Refund Events and Statuses
event | orderStatus | Meaning |
|---|---|---|
QR_CODE_COPY_AND_PASTE_REFUNDED | SUCCESS | PIX QR code cashin/acquiring — refund succeeded. |
QR_CODE_COPY_AND_PASTE_REFUNDED_ERROR | FAILED | PIX QR code cashin/acquiring — refund failed. |
The callback only notifies final refund states. While the refund is still PENDING, no result notification is sent; the partner can query the current status through the refund order query API.
5. Request Example
The following example shows a first successful refund on the original order: principal 50.00 and fee 0.30 refunded; accumulated refund principal 50.00; accumulated refunded fees 0.30.
POST /notify/adopay/cashin/refund HTTP/1.1
Host: merchant.example.com
Content-Type: application/json
X-Merchant-Id: 92315566000120
X-Timestamp: 1786838460
X-Nonce: 4de901987ca14b25acf2639056ac6002
Digest: SHA-256=<REQUEST_BODY_SHA256_BASE64>
Authorization: Signature keyId="v1",alg="ES256",headers="(request-target) x-timestamp x-nonce digest",signature="<ES256_SIGNATURE_BASE64>"
{
"status": 200,
"msg": "sucesso",
"event": "QR_CODE_COPY_AND_PASTE_REFUNDED",
"subMerchantNo": "SUB00000001",
"attach": "order-source=checkout",
"merchantOrderNo": "REFUND202608160001",
"platOrderNo": "RFD202608160000000001",
"origMerchantOrderNo": "CASHIN202608160001",
"origPlatOrderNo": "BAS202608160000000001",
"origAmount": 100.00,
"origTotalRefundAmount": 50.00,
"origTotalFeeRefundAmount": 0.30,
"amount": 50.00,
"refundAmount": 50.00,
"feeRefundAmount": 0.30,
"currency": "BRL",
"e2eId": "E1234567820260816000000000000001",
"orderStatus": "SUCCESS",
"refundTime": 1786887025
}6. Partner Response Requirements
After completing signature verification, idempotent processing, and persisting the business data, the partner should return HTTP 200—299 with a response body of exactly the plain text SUCCESS or OK:
HTTP/1.1 200 OK
Content-Type: text/plain
SUCCESS7. Notification Scenarios and Retries
When a cashin refund succeeds or fails, Adopay sends a callback notification to the partner.
After the first delivery attempt of a notification fails, Adopay retries at most 9 times, for at most 10 deliveries in total. Once the partner receives the notification successfully and returns the required success response, no further retries occur.
Whether to retry is determined jointly by the HTTP status code and the response body:
| HTTP Status Code | Response Body | Result |
|---|---|---|
200—299 | Strictly equal to SUCCESS or OK after trimming leading and trailing whitespace | Notification delivered; no more retries |
200—299 | Empty body, JSON, other text, or wrong casing | Notification failed; retry continues |
Non-2xx | Any content | Notification failed; retry continues |
| No HTTP response received | Network timeout or connection failure | Notification failed; retry continues |
SUCCESS and OK are case-sensitive. For example, success, Success, or {"status":"SUCCESS"} are not recognized as success responses. Although HTTP 204 is a 2xx status, its body is empty, so retries continue.
X-Timestamp, X-Nonce, Digest, and Authorization are regenerated for each delivery.
8. Integration Notes
- Use the primary merchant ID + merchant refund order number, or
platOrderNo, as an equivalent unique key; do not judge duplicates by the number of notifications received. - The partner should complete signature verification first, then validate the primary merchant ID, sub-merchant ID, original order number, refund order number, currency, and amount, and update the refund result only after everything matches.
- Include
e2eIdand order numbers in audit records; where merchant, payer, or channel sensitive information is involved, logs should mask it or record only digests. - Return the required success response only after signature verification, idempotent processing, and data persistence all succeed, so the notification is not incorrectly acknowledged and lost to retries.