> ## Documentation Index
> Fetch the complete documentation index at: https://docs.compago.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Process Refunds

> Issue full refunds for charges made against saved payment methods.

You can refund charges made against saved payment methods. Refunds are always for the full charge amount and are processed through Compago's infrastructure. The funds are returned to the customer's original payment method.

## Endpoint

```
POST /api/payment-method/{id}/payment/{paymentId}/refund
```

**API reference:** [`POST /payment-method/{id}/payment/{paymentId}/refund`](/api-reference/payment-method/refund)

### Authentication

Include your API key in the request headers:

```
x-api-key: YOUR_API_KEY
Content-Type: application/json
```

### Path Parameters

<ParamField path="id" type="string" required>
  The unique identifier of the payment method (UUID).
</ParamField>

<ParamField path="paymentId" type="string" required>
  The unique identifier of the payment to refund (UUID).
</ParamField>

### Request Body

```json theme={null}
{
  "reason": "Customer requested refund"
}
```

| Field    | Type   | Required | Description                                                         |
| -------- | ------ | -------- | ------------------------------------------------------------------- |
| `reason` | string | No       | Reason for the refund. Useful for accounting and auditing purposes. |

### Response

```json theme={null}
{
  "id": "11111111-2222-3333-4444-555555555555",
  "status": "REFUNDED",
  "amount": 500,
  "currency": "MXN"
}
```

| Field      | Type   | Description                               |
| ---------- | ------ | ----------------------------------------- |
| `id`       | string | Unique identifier of the payment.         |
| `status`   | string | Payment status after refund (`REFUNDED`). |
| `amount`   | number | The refunded amount.                      |
| `currency` | string | Currency code.                            |

## Code Examples

The entire original charge amount will be refunded.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.harmony.compago.com/api/payment-method/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/payment/11111111-2222-3333-4444-555555555555/refund \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "reason": "Customer requested cancellation"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    `https://api.harmony.compago.com/api/payment-method/${paymentMethodId}/payment/${paymentId}/refund`,
    {
      method: 'POST',
      headers: {
        'x-api-key': process.env.COMPAGO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        reason: 'Customer requested cancellation'
      })
    }
  );

  const refund = await response.json();
  console.log('Refund status:', refund.status);
  console.log('Refunded amount:', refund.amount, refund.currency);
  ```

  ```python Python theme={null}
  response = requests.post(
      f'https://api.harmony.compago.com/api/payment-method/{payment_method_id}/payment/{payment_id}/refund',
      headers={
          'x-api-key': os.environ['COMPAGO_API_KEY'],
          'Content-Type': 'application/json'
      },
      json={
          'reason': 'Customer requested cancellation'
      }
  )

  refund = response.json()
  print('Refund status:', refund['status'])
  print('Refunded amount:', refund['amount'], refund['currency'])
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init("https://api.harmony.compago.com/api/payment-method/{$paymentMethodId}/payment/{$paymentId}/refund");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'x-api-key: ' . getenv('COMPAGO_API_KEY'),
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'reason' => 'Customer requested cancellation'
  ]));

  $response = curl_exec($ch);
  $refund = json_decode($response, true);
  curl_close($ch);

  echo "Refund status: {$refund['status']}" . PHP_EOL;
  echo "Refunded amount: {$refund['amount']} {$refund['currency']}" . PHP_EOL;
  ?>
  ```

  ```ruby Ruby theme={null}
  uri = URI("https://api.harmony.compago.com/api/payment-method/#{payment_method_id}/payment/#{payment_id}/refund")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = ENV['COMPAGO_API_KEY']
  request['Content-Type'] = 'application/json'
  request.body = {
    reason: 'Customer requested cancellation'
  }.to_json

  response = http.request(request)
  refund = JSON.parse(response.body)

  puts "Refund status: #{refund['status']}"
  puts "Refunded amount: #{refund['amount']} #{refund['currency']}"
  ```
</CodeGroup>

## Refund Rules

<Warning>
  **Only CONFIRMED payments can be refunded.** Attempting to refund a payment with any other status (`NOT_INITIALIZED`, `PENDING`, `CANCELLED`, `REFUNDED`) will result in a 400 error.
</Warning>

<Note>
  **Refunds are permanent.** Once a refund is processed, it cannot be reversed. The payment status changes to `REFUNDED`.
</Note>

## Error Handling

| Status Code | Error                    | Solution                                               |
| ----------- | ------------------------ | ------------------------------------------------------ |
| 400         | Payment not CONFIRMED    | Only payments with `CONFIRMED` status can be refunded. |
| 401         | Unauthorized             | Check your API key is valid and included in headers.   |
| 404         | Payment method not found | Verify the payment method ID is correct.               |
| 404         | Payment not found        | Verify the payment ID is correct.                      |

## Best Practices

<AccordionGroup>
  <Accordion title="Verify Payment Status Before Refunding">
    Always check that the payment status is `CONFIRMED` before attempting a refund to avoid unnecessary API errors.

    ```javascript theme={null}
    const payment = await fetchPayment(paymentMethodId, paymentId);
    if (payment.status !== 'CONFIRMED') {
      console.error('Cannot refund - payment status is', payment.status);
      return;
    }
    // Proceed with refund
    ```
  </Accordion>

  <Accordion title="Track Refund Reasons">
    Always include a `reason` field when processing refunds. This helps with accounting, auditing, and customer service.

    ```json theme={null}
    {
      "reason": "Customer returned item #SKU-1234"
    }
    ```
  </Accordion>

  <Accordion title="Implement Idempotent Refund Logic">
    Protect against duplicate refund requests by checking if the payment has already been refunded before making the API call.

    ```javascript theme={null}
    const payment = await fetchPayment(paymentMethodId, paymentId);
    if (payment.status === 'REFUNDED') {
      console.log('Payment already refunded');
      return;
    }
    ```
  </Accordion>

  <Accordion title="Communicate Refund Timelines to Customers">
    Refund processing times depend on the customer's bank. Let customers know that while the refund is processed immediately on Compago's side, it may take a few business days to appear on their statement.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Manage Payment Methods" icon="list" href="/payment-method/manage">
    List, retrieve, and revoke saved payment methods.
  </Card>

  <Card title="Payment Methods Overview" icon="vault" href="/payment-method/overview">
    Review payment method statuses, use cases, and how the feature works.
  </Card>
</CardGroup>
