Miracle Docs

Refunds

Return funds to the customer after a successful payment. You can refund the full amount or issue multiple partial refunds.


Create a refund

Call POST /v1/payments/{id}/refunds to initiate a refund. Omit the amount field for a full refund, or include it for a partial refund.

Full refund

curl -X POST https://api.miracle.com/v1/payments/pay_abc123/refunds \
  -H "Authorization: Bearer sk_test_your_secret_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-order-1234" \
  -d '{
    "reason": "Customer requested cancellation"
  }'
const response = await fetch('https://api.miracle.com/v1/payments/pay_abc123/refunds', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_test_your_secret_key',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'refund-order-1234',
  },
  body: JSON.stringify({
    reason: 'Customer requested cancellation',
  }),
});

const { data: refund } = await response.json();
// refund.status === 'pending' or 'processing'

Partial refund

Pass an amount to refund less than the original payment:

curl -X POST https://api.miracle.com/v1/payments/pay_abc123/refunds \
  -H "Authorization: Bearer sk_test_your_secret_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-order-1234-item-a" \
  -d '{
    "amount": {
      "currency": "USD",
      "valueMinor": 2500
    },
    "reason": "Item returned",
    "merchantReference": "return-item-a"
  }'
const response = await fetch('https://api.miracle.com/v1/payments/pay_abc123/refunds', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_test_your_secret_key',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'refund-order-1234-item-a',
  },
  body: JSON.stringify({
    amount: {
      currency: 'USD',
      valueMinor: 2500,
    },
    reason: 'Item returned',
    merchantReference: 'return-item-a',
  }),
});

const { data: refund } = await response.json();
// refund.amount.valueMinor === 2500

Async behavior

Refunds are processed asynchronously. The API response returns the refund with an initial status (pending or processing), but the final result arrives via webhook.

  1. You call POST /v1/payments/{id}/refunds — response returns the Refund object.
  2. The provider processes the refund (may take seconds or minutes).
  3. Miracle sends a refund.succeeded or refund.failed webhook.
  4. Your webhook handler updates the order accordingly.

Do not retry on timeout. If your request times out, check the refund status via GET /v1/payments/{id}/refunds or wait for the webhook before attempting another refund. Duplicate refund requests with a different Idempotency-Key will create a second refund.


Refund statuses

StatusDescriptionTerminal
pendingRefund created, awaiting processing.No
processingRefund submitted to the payment provider.No
requires_actionProvider requires payer confirmation (non-card methods only, e.g., bank transfer).No
succeededRefund completed, funds returned to customer.Yes
failedRefund rejected by the provider.Yes
canceledRefund canceled before completion.Yes

Webhooks

You receive webhook events as the refund progresses:

EventWhen
refund.createdRefund has been created.
refund.succeededRefund completed successfully. Funds returned to customer.
refund.failedRefund was rejected by the provider.

When a refund succeeds, the parent payment status also updates:

EventWhen
payment.refundedFull refund completed.
payment.partially_refundedPartial refund completed, remaining balance still captured.

Rules and limits

  • Eligible payments only. You can only refund payments in succeeded, captured, or partially_refunded status.
  • Currency must match. The refund currency must be the same as the original payment currency.
  • Multiple partial refunds allowed. You can issue several partial refunds against the same payment. The total of all refunds cannot exceed the original captured amount.
  • Full refund closes the payment. After a full refund, the payment status becomes refunded and no further refunds are possible.
  • Refund timing. After a successful refund, the time for funds to appear on the customer's statement depends on the payment method and issuer.

Retrieve refunds

Single refund by ID

curl https://api.miracle.com/v1/refunds/ref_xyz789 \
  -H "Authorization: Bearer sk_test_your_secret_key"

All refunds for a payment

curl https://api.miracle.com/v1/payments/pay_abc123/refunds \
  -H "Authorization: Bearer sk_test_your_secret_key"

Both endpoints return the Refund object with all fields including status, amount, reason, providerReference, and statusReason (a human-readable explanation from the provider when a refund fails).


Request fields reference

FieldTypeRequiredDescription
amountMoneyAmountNoAmount to refund. Omit for full refund.
reasonstringNoReason for the refund (for your records and provider).
merchantReferencestringNoYour internal reference for this refund.
itemsLineItem[]NoLine items being refunded (pass-through metadata).
metadataobjectNoKey-value pairs for your own use.

On this page