# Refunds

The Refunds API lets merchants return funds to a payer after a payment request reaches a refundable state. Refunds are scoped to the organization or account that owns the payment request's point of sale.

## Overview

When you create a refund, Fluxis:

1. Validates that your API credentials can access the payment request's POS
2. Checks that the payment request is in an eligible status
3. Creates a refund record in `processing` status
4. Sends a `refund` webhook (if configured) with the initial status

::::warning
**On-chain execution is not yet implemented.** Refund records are created and webhooks are dispatched, but the blockchain transfer that sends funds to `refund_to_address` is still pending implementation in the refund processing service.
::::

## Eligible payment request statuses

Refunds can only be created when the payment request is in one of these statuses:

| Status | Typical use |
| ------ | ----------- |
| `completed` | Full payment received; refund the paid amount |
| `overpaid` | Payer sent more than requested |
| `underpaid` | Payer sent less than requested |
| `confirmed` | Ledger transaction created after payment |

Payment requests in `pending`, `created`, `processing`, `expired`, or `failed` are **not** eligible.

## Authentication

All refund endpoints require both headers:

- `Authorization: Bearer <access_token>`
- `x-fluxis-api-key: <your_api_key>`

See [Authentication & Configuration](/docs/merchant-integration/auth-and-conf) for token exchange.

## Create a refund

```
POST /v1/refunds/payment-request/{paymentRequestID}
```

### Request body

| Field | Required | Description |
| ----- | -------- | ----------- |
| `refund_to_address` | Yes | Blockchain address that will receive the refund |
| `amount` | No | Decimal string. If omitted, defaults to the payment request's recorded amount |
| `reason` | No | Free-text reason for audit purposes |

### Example

```bash
curl -X POST "https://api.fluxis.us/v1/refunds/payment-request/aa5d6c80-0b0b-4a2a-bbc8-14a41e6245bf" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-fluxis-api-key: fxs.prd.YOUR_KEY_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "refund_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "amount": "50.00",
    "reason": "Customer overpaid"
  }'
```

### Response (`200`)

```json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "refund_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "amount": "50.00",
    "status": "processing"
  }
}
```

::::note
When `amount` is omitted, the refund uses the payment request's stored amount. For `overpaid` or `underpaid` requests, that value reflects the amount actually received on chain.
::::

## Get refund details

```
GET /v1/refunds/{refundID}
```

Returns full refund metadata including network, asset, original payment transaction hash, and `refund_transaction_hash` once on-chain processing completes.

| Field | Description |
| ----- | ----------- |
| `status` | `processing`, `completed`, or `failed` |
| `payment_transaction_hash` | Hash of the original inbound payment |
| `refund_transaction_hash` | Outbound refund hash (present after on-chain execution) |
| `unique_asset_id` | Asset identifier (e.g. Polygon USDC) |
| `network` | Blockchain network for the refund |

You can only retrieve refunds that were created by the same authenticated entity (organization or account).

## Refund statuses

| Status | Meaning |
| ------ | ------- |
| `processing` | Refund record created; on-chain transfer pending |
| `completed` | Refund transaction confirmed on chain |
| `failed` | Refund could not be completed |

Today, newly created refunds remain in `processing` until on-chain execution is implemented.

## Webhooks

Register a webhook with `event_type: "refund"` at the account level. On create, Fluxis sends:

```json
{
  "data": {
    "notification_type": "refund_status_update",
    "refund_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "payment_request_id": "aa5d6c80-0b0b-4a2a-bbc8-14a41e6245bf",
    "status": "processing",
    "amount": "50.00"
  }
}
```

Verify every delivery using [Webhook Signature Verification](/docs/developers/webhook-signature-verification). See [Webhook Events](/docs/developers/webhook-events) for the full event catalog.

## Common errors

| HTTP | Cause |
| ---- | ----- |
| `400` | Invalid payment request ID, amount, or ineligible payment request status |
| `403` | API credentials lack permission for the payment request's POS |
| `404` | Refund not found (GET only) |

## Related documentation

- [Payment Requests](/docs/key-concepts/payment-request) — lifecycle and edge-case states
- [Webhook Events](/docs/developers/webhook-events) — `refund` event payload
- [Transactions](/docs/developers/transactions) — ledger records after payment confirmation
