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

# Refunds

> Process refunds in the DVM.

## Overview

When you use the DVM's Billing & Charging capability, Bango manages the full billing lifecycle on your behalf — collecting charges and issuing refunds for the subscription offers you create in the DVM Offer Catalog. Refunds are sent directly to your billing system via a `POST /refunds` request, and your system is responsible for processing and acknowledging each one.

<Info>
  Refunds are only issued when you have licensed the DVM's Billing & Charging capability. If you manage billing externally, refund handling is your responsibility.
</Info>

***

## When refunds are issued

There are three scenarios in which the DVM will issue a refund to your billing system:

<CardGroup cols={2}>
  <Card title="Downgrade" icon="circle-down">
    A consumer moves to a lower-priced product tier mid-cycle. They receive a **pro-rated refund** of the price difference for the unused days remaining in the billing period.
  </Card>

  <Card title="Immediate Cancellation" icon="circle-xmark">
    A consumer immediately cancels their offer, ending the billing lifecycle. They receive a **pro-rated refund** against their last renewal charge for the unused days remaining.
  </Card>

  <Card title="Right to Withdrawal" icon="scale-balanced">
    In certain circumstances, a consumer may be automatically eligible for a **full refund** following cancellation — for example, if they cancel within a statutory right-to-withdrawal period.
  </Card>
</CardGroup>

<Tip>
  For pro-rated refund calculations — including how remaining days are counted and the formula used — see the [Pro-ration](/billing-and-charging/pro-ration) page.
</Tip>

***

## Refund types

The DVM issues two types of refund requests to your billing system, depending on the scenario:

| Refund type | `billType` value | When used |
| - | - | - |
| Pro-rated refund | `PRO_RATED_REFUND` | Downgrade or immediate cancellation mid-cycle |
| Full refund | `FULL_REFUND` | Right to Withdrawal |

***

## Example refund request

Below is an example of a `PRO_RATED_REFUND` request your billing system will receive from the DVM. This represents a consumer who has downgraded their product entitlement mid-cycle.

```json theme={null}
{
  "requestId": "f8e7d6c5-b4a3-4c2b-8d1e-9f0a1b2c3dff",
  "billEffectiveDate": "2026-03-15T14:27:33.000Z",
  "billType": "PRO_RATED_REFUND",
  "billId": "ca11419d-8143-43f2-af5d-0259b85a2fca",
  "originalChargeId": "c699aa49-35ea-4a23-9c3e-4479413db91d",
  "refundId": "d56442de-ca64-411f-8585-830291b3d6cf",
  "refundAttempt": 0,
  "isRetry": false,
  "amount": 750,
  "currency": "USD",
  "consumer": {
    "consumerIdentifier": "RFBNZ2MU3Y35OA5GNNNGETK6JTEVRYVB",
    "billingIdentifier": "BWNMJXEDAO7HTK6Q4SBAOEJMPGURUB3K"
  },
  "resourceType": "CONSUMER_OFFER",
  "consumerOffer": {
    "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51",
    "offerId": "7560fca0-d8a9-4124-a172-924debec874e",
    "entitlements": [
      {
        "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
        "contentProviderId": "NETFLIX",
        "productId": "Netflix",
        "productTierKey": "NETFLIX_STD"
      }
    ]
  },
  "billingDetails": {
    "planType": "SUBSCRIPTION",
    "billingPeriod": {
      "duration": "P1M",
      "startDate": "2026-01-01T01:00:00.000Z",
      "endDate": "2026-02-01T00:59:59.999Z",
      "phaseType": "FULL_PRICE"
    }
  },
  "lineItems": [
    {
      "lineItemType": "OFFER_TIER_CHANGE_PRORATION",
      "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
      "amount": 750,
      "currency": "USD",
      "quantity": 1
    }
  ]
}
```

### Key fields explained

These are the fields most important for your billing system to understand and act on:

<ResponseField name="requestId" type="string" required>
  A Bango-generated UUID for this request. **You must echo this back in your response** — it's how Bango correlates requests and responses.
</ResponseField>

<ResponseField name="billType" type="string" required>
  Tells you the type of refund being issued. Either `PRO_RATED_REFUND` (partial, mid-cycle) or `SINGLE_REFUND` (full refund).
</ResponseField>

<ResponseField name="originalChargeId" type="string" required>
  The unique ID of the original charge transaction that this refund relates to. Use this to locate and reverse the correct payment in your system.
</ResponseField>

<ResponseField name="refundId" type="string" required>
  A unique identifier for this specific refund transaction. Note that a single charge can have more than one partial refund, each with its own `refundId`.
</ResponseField>

<ResponseField name="amount" type="integer" required>
  The total refund amount, expressed in **minor currency units** (e.g. cents, pence). For example, `750` = \$7.50 USD.
</ResponseField>

<ResponseField name="currency" type="string" required>
  The currency of the refund in ISO 4217 format (e.g. `USD`, `GBP`, `EUR`).
</ResponseField>

<ResponseField name="isRetry" type="boolean" required>
  Indicates whether this is a retry of a previously failed refund attempt. If `true`, check `refundAttempt` to see which attempt number this is. Use `refundId` to identify and deduplicate the refund in your system.
</ResponseField>

<ResponseField name="refundAttempt" type="integer" required>
  The attempt number for this refund. `0` = first attempt, `1` = first retry, and so on.
</ResponseField>

<ResponseField name="lineItems" type="array" required>
  The breakdown of what is being refunded. For pro-rated refunds on tier changes, the `lineItemType` will be `OFFER_ENTITLEMENT_TIER_DELTA`, with the amount representing the pro-rated price delta. For full refunds, `lineItemType` will be `SINGLE_REFUND`.
</ResponseField>

<ResponseField name="billingDetails.billingPeriod" type="object">
  The billing period the refund relates to, including `startDate`, `endDate`, `duration` (ISO 8601), and `phaseType` (`FREE`, `DISCOUNT`, or `FULL_PRICE`). Useful for reconciliation.
</ResponseField>

***

## How to respond

Your billing system must respond to every refund request with a `200` status and a JSON body indicating whether the refund was processed or declined.

### Approved

Return this when the refund has been successfully processed in your billing system:

```json theme={null}
{
  "requestId": "f8e7d6c5-b4a3-4c2b-8d1e-9f0a1b2c3dff",
  "responseCode": "APPROVED"
}
```

### Declined

Return this when you are unable to process the refund. You must include a `reason` code so Bango can determine whether to retry:

```json theme={null}
{
  "requestId": "f8e7d6c5-b4a3-4c2b-8d1e-9f0a1b2c3dff",
  "responseCode": "DECLINED",
  "reason": "REFUND_PERIOD_EXPIRED",
  "reasonDescription": "Refund period expired"
}
```

### Decline reason codes

The `reason` field tells Bango why the refund was declined and whether a retry should be attempted:

| Reason code | Meaning | Bango will retry? |
| - | - | - |
| `DENIED` | General denial — the refund was refused without a more specific reason | ❌ No |
| `USER_INVALID` | The consumer identifier is not recognised, or the account has been closed | ❌ No |
| `REFUND_PERIOD_EXPIRED` | The refund was requested after your allowed refund window | ❌ No |
| `ALREADY_IN_PROGRESS` | A refund with the same `refundId` is already being processed — prevents duplicates | ⏳ Bango will wait before retrying |

<Warning>
  If you return `DECLINED` with no `reason`, or return an unexpected response code, Bango may treat it as a processing error and retry the refund. Always include a valid `reason` to ensure predictable behavior.
</Warning>
