Skip to main content

Refunds

Flowlix supports full refunds on any payment that has the succeeded status. When you refund a payment, the full amount is returned to the customer’s card.

How refunds work

  • Refunds are full only — the entire payment amount is returned.
  • A payment can only be refunded once.
  • The payment status changes from succeeded to refunded.
  • The refunded_at field is set to the Unix timestamp of the refund.
  • Refunds are processed synchronously — the response confirms the refund immediately.

Create a refund

Send a POST request to /v1/payments/{id}/refund:
curl -X POST https://api.flowlix.eu/v1/payments/pay_1N3fKx2eZvKYlo2C0XjMr8pV/refund \
  -H "Authorization: Bearer fl_test_sk_abc123def456" \
  -H "Idempotency-Key: refund-order-1234"
No request body is needed — the endpoint always refunds the full amount.

Successful response

{
  "id": "pay_1N3fKx2eZvKYlo2C0XjMr8pV",
  "object": "payment",
  "amount": 4999,
  "currency": "eur",
  "status": "refunded",
  "description": "Order #1234",
  "card": {
    "brand": "visa",
    "last4": "4242",
    "exp_month": 12,
    "exp_year": 2027,
    "country": "US"
  },
  "customer": {
    "email": "jenny@example.com",
    "name": "Jenny Rosen"
  },
  "metadata": {
    "order_id": "ord_1234"
  },
  "decline_code": null,
  "decline_message": null,
  "redirect_url": null,
  "refunded_at": 1719878400,
  "succeeded_at": 1719792000,
  "failed_at": null,
  "created": 1719792000,
  "livemode": false
}

Error scenarios

Payment already refunded

If you try to refund a payment that is already refunded:
{
  "error": {
    "type": "invalid_request_error",
    "code": "payment_already_refunded",
    "message": "This payment has already been refunded.",
    "param": null,
    "decline_code": null,
    "doc_url": "https://docs.flowlix.eu/guides/refunds",
    "request_id": "req_abc123def456"
  }
}
HTTP status: 422 Unprocessable Entity

Payment not found

If the payment ID does not exist:
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such payment: pay_nonexistent123",
    "param": "id",
    "decline_code": null,
    "doc_url": "https://docs.flowlix.eu/api-reference/errors",
    "request_id": "req_abc123def456"
  }
}
HTTP status: 404 Not Found

Payment not in succeeded status

Only succeeded payments can be refunded. If you try to refund a pending or failed payment:
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Payment pay_xxx is not in a refundable state. Current status: pending.",
    "param": "id",
    "decline_code": null,
    "doc_url": "https://docs.flowlix.eu/guides/refunds",
    "request_id": "req_abc123def456"
  }
}
HTTP status: 422 Unprocessable Entity

Integration example

import requests

FLOWLIX_API_KEY = "fl_test_sk_abc123def456"

def refund_payment(payment_id, idempotency_key=None):
    """Refund a payment by ID."""
    headers = {
        "Authorization": f"Bearer {FLOWLIX_API_KEY}",
    }
    if idempotency_key:
        headers["Idempotency-Key"] = idempotency_key

    response = requests.post(
        f"https://api.flowlix.eu/v1/payments/{payment_id}/refund",
        headers=headers,
    )

    if response.status_code == 200:
        payment = response.json()
        print(f"Refunded payment {payment['id']} - amount: {payment['amount']}")
        return payment

    error = response.json()["error"]

    if error["code"] == "payment_already_refunded":
        print(f"Payment {payment_id} was already refunded")
    elif error["code"] == "resource_missing":
        print(f"Payment {payment_id} not found")
    else:
        print(f"Refund failed: {error['message']}")

    return None


# Usage
refund_payment(
    "pay_1N3fKx2eZvKYlo2C0XjMr8pV",
    idempotency_key="refund-order-1234"
)

Checking refund status

You can check whether a payment has been refunded by retrieving it:
curl https://api.flowlix.eu/v1/payments/pay_1N3fKx2eZvKYlo2C0XjMr8pV \
  -H "Authorization: Bearer fl_test_sk_abc123def456"
Check the status and refunded_at fields in the response:
  • "status": "refunded" — the payment has been refunded.
  • "refunded_at": 1719878400 — the Unix timestamp when the refund was processed.
You can also filter the payments list to find all refunded payments:
curl "https://api.flowlix.eu/v1/payments?status=refunded&limit=50" \
  -H "Authorization: Bearer fl_test_sk_abc123def456"

Best practices

  • Always use an Idempotency-Key when refunding to prevent duplicate refunds on retries.
  • Use a deterministic key tied to the refund operation (e.g., refund-order-{order_id}).
  • Check the payment status first if you want to show a preview to the user before confirming.
  • Log the request_id from refund responses for audit and support purposes.
  • Handle the “already refunded” case gracefully — treat it as a success in your UI, not an error.