Appearance
Refunds
Pine Labs records refund obligations for failed fulfillment and duplicate collections. Supported CARD refunds are returned on the order and through refund webhooks.
Automatic refunds
Refunds are automatic for CARD payments; FPX is not supported. Repayment is confirmed only when the refund status is successful.
| Reason | Amount | When |
|---|---|---|
failed_fulfillment | Sum of failed units' frozen sale prices, rounded to two decimals per unit; excludes customer fees. | One aggregate refund against the order's winning payment, after all units finish. |
duplicate_collection | Entire extra collection, including its customer fee. | A separately confirmed duplicate collection; never fulfills the order again. |
If the RM60 item succeeds and the RM40 item fails, the order gets one RM40 refund. If every item fails, refund the full item subtotal; the fee remains unchanged. For quantity three with one failed unit, refund one unit's sale price. No refund is created when all units succeed.
Additional duplicate collections require their own refunds. Read refund summaries in refunds on order detail, or receive individual refund events.
Order refund summaries
The order's refunds array contains summaries for that order, grouped by payment_id and status. Each entry has only payment_id, amount, and status; amount is the sum for that group. These are not individual refund records. A duplicate collection can create a refund against a different payment on the same order.
json
{
"refunds": [
{ "payment_id": "pay_example", "amount": "40.00", "status": "pending" }
]
}Refund event schema
Refund webhook data describes an individual refund with the fields below. It has a different shape from the order's refund summaries.
| Field | Type | Description |
|---|---|---|
refund_id | string | Stable identifier through processing and review. |
order_id | string | Order receiving the refund. |
payment_id | string | Original collection being repaid; not a per-item allocation. |
currency | string | MYR. |
amount | string | Positive two-place refund amount. |
reason | string | failed_fulfillment or duplicate_collection. |
status | string | pending, requires_review, or successful. |
created_at | string | UTC refund creation time. |
updated_at | string | UTC time of the latest public refund change. |
Refund example
json
{
"refund_id": "ref_example",
"order_id": "ord_example",
"payment_id": "pay_example",
"currency": "MYR",
"amount": "40.00",
"reason": "failed_fulfillment",
"status": "pending",
"created_at": "2026-09-14T02:15:20.000Z",
"updated_at": "2026-09-14T02:15:20.000Z"
}Refund progress
| Status | Meaning |
|---|---|
pending | Repayment obligation exists; it may be queued or awaiting provider confirmation. |
requires_review | Submission was rejected or its outcome is uncertain; Pine Labs is reviewing it. |
successful | Customer repayment is verified. |
Order completed does not mean repayment finished. Wait for refund successful; do not independently refund a payment under review. Status checks and review retain the same refund ID.
successful means the customer repayment is verified. The winning payment's merchant fee remains billable even when every unit fails; duplicate collections create neither another fulfillment nor an extra merchant fee.

