> For the complete documentation index, see [llms.txt](https://developers.bead.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.bead.xyz/payments/rebate-program.md).

# Rebate Program

## Rebate Program

The Rebate Program lets a partner decide, per payment, exactly how much a merchant keeps. The consumer pays the full ticket, the merchant is settled the agreed amount with no transaction fee deducted, and Bead withholds the difference and later pays it to the partner.

Use this page when a merchant is enrolled in the Rebate Program. For standard payment creation, see [Create Payment](/payments/create-payment.md).

> **Why "rebate"?** The name describes what happens to the partner's share, not the merchant's. Neither the merchant nor the consumer gets anything back here. The partner does: `targetRebate` is calculated from the transaction, withheld, and paid out to the partner on a periodic distribution, the same way a rebate line shows up on a residual statement from other processors.

> **You will almost certainly be collecting a consumer fee to use this.** `targetRebate` only exists because `total` is set higher than what the merchant expects to net, and the only way to do that is to fold a fee into the amount yourself before payment creation. There is no fee field on this endpoint and no Bead capability that calculates or collects one. In practice, using this program means you are collecting a consumer fee whether or not you think of it under that name, and the state-by-state and per-tender legal considerations in [Consumer Fee Passthrough for Wallet and Crypto Tenders](/faqs-and-troubleshooting/payments-faqs/consumer-fee-passthrough-for-wallet-and-crypto-tenders.md) apply directly to your integration, not by association. Read that page before you build against this one. See [Collecting a consumer fee alongside this program](#collecting-a-consumer-fee-alongside-this-program) for the pattern.

### How it differs from standard processing

On standard processing, Bead calculates the transaction fee from the merchant's fee configuration and deducts it from the merchant's settlement.

On the Rebate Program:

* Your integration sends the exact amount the merchant should keep.
* Bead settles that amount, with no transaction fee applied. The merchant's fee configuration is not consulted at all.
* The remainder is withheld at settlement and paid to the partner on a schedule, net of a Bead rebate fee.
* The merchant is never billed afterwards and never sees a later deduction.

Enrolled merchants can still send ordinary payments. Omit the `rebate` block and the payment is processed normally. Mixed traffic on one merchant is supported and the two kinds settle side by side.

### The three amounts

Every rebate payment carries three amounts.

| Amount            | Description                                                               |
| ----------------- | ------------------------------------------------------------------------- |
| `total`           | What the consumer pays. Must exactly equal `requestedAmount`.             |
| `merchantPortion` | The exact amount settled to the merchant. No transaction fee is deducted. |
| `targetRebate`    | The amount withheld at settlement for later distribution to the partner.  |

#### The rule that must always hold

`merchantPortion + targetRebate` must exactly equal `total`.

There is no remainder and no rounding tolerance. A payment that breaks this is rejected with `400 Bad Request`.

`total` must also equal `requestedAmount`. If your integration changes the ticket amount, all four values have to move together.

All amounts are limited to two decimal places.

### Bead's rebate fee

Bead deducts a fee from `targetRebate` before paying the partner. It is calculated per payment and never touches `merchantPortion`, only the withheld portion:

```
partnerNet = targetRebate - rebateFee
```

A payment whose `targetRebate` does not cover the rebate fee is still accepted and is not a validation error, and your merchant is still settled correctly.

> **This failure is silent, and it is the most important thing to get right before go-live.** An underwater payment does not error and does not stall your payout. Its negative amount is netted into your distribution total, so a $10.00 line and a −$2.00 line pay out $8.00. Bead collects its fee either way; you simply receive less than you expected. Nothing surfaces at the point of sale, so a mis-sized consumer fee can erode a month of distributions before anyone reconciles. Check the distribution summary against your own expectations, per tender, in your first month.

A distribution only blocks outright when it nets to zero or less as a whole, or when one of the prerequisites below is missing.

**There is no standard rebate rate.** The fee is the partner's own contracted rate with Bead, the same rate card that governs their other business, so it differs from partner to partner and can differ per payment method. It resolves from the partner record, not from the merchant's fee configuration, and it cannot be sent on the payment. Confirm your actual rates with your Bead contact before sizing a consumer fee schedule against them.

The fee has two components, both deducted from `targetRebate`:

| Component           | Applied to        |
| ------------------- | ----------------- |
| Percentage          | `merchantPortion` |
| Per-transaction fee | Each payment      |

**The percentage applies to `merchantPortion`, not `total`.** The base is the amount your merchant is settled, not the amount the consumer paid. The deduction still comes out of `targetRebate`, so a larger merchant portion means a larger fee drawn from a smaller withheld amount.

**The settlement fee is not part of this calculation.** It is charged per settlement event, meaning once per deposit, exactly as on standard processing. It is not a per-payment charge.

**The fee is calculated at assessment, not at payment creation.** The rate is read as of the payment's capture date, so the result is stable, but the fee is not present on the payment record at transaction time and there is no fee field on the transaction report. You will see it on the distribution summary.

Because the per-transaction fee is flat, low-value tickets need a proportionally larger `targetRebate` for you to earn anything. Where `c` is the consumer fee rate you charge and `p` is your percentage rate with Bead:

```
break-even merchantPortion = perTransactionFee / (c - p)
```

Model your fee structure against the smallest ticket you expect to process, not the average one.

> **Rebate and residuals are mutually exclusive.** A partner on this program takes their margin at transaction time, through `targetRebate`. Residuals are derived from fees Bead collects from the merchant, and on this program the merchant is charged nothing, so there is no residual to calculate. Traffic moved onto this program stops generating residuals. See [Residual Reporting](/settlement/residual-reporting.md).

#### Expect your distribution to differ from the residual it replaces

Model this before you move traffic onto the program. On standard processing your margin derives from fees Bead charged your merchant and reaches you as a month-end residual. Here the merchant is charged nothing, so your margin is the consumer fee you collected less Bead's fee, paid as a distribution. The two are calculated from entirely different things and will not be the same size. Work it through with your own rates rather than assuming a like-for-like replacement.

### Worked example

A rebate payment where the merchant keeps less than the full ticket, with the difference withheld for the partner.

| Step                                      | What it represents                             |
| ----------------------------------------- | ---------------------------------------------- |
| Consumer pays (`total`)                   | The full ticket amount                         |
| Merchant is settled (`merchantPortion`)   | The agreed amount, no transaction fee deducted |
| Withheld for the partner (`targetRebate`) | `total` minus `merchantPortion`                |
| Bead's rebate fee                         | Deducted from `targetRebate` only, see above   |
| Partner receives (`partnerNet`)           | `targetRebate` minus Bead's rebate fee         |

The merchant sees exactly `merchantPortion` on their daily settlement, regardless of what Bead's fee ends up being.

### Collecting a consumer fee alongside this program

**Bead has no consumer fee capability.** There is no fee field on the payment, no rate configuration, and nothing in the API that calculates, displays or collects a consumer fee. Sizing and disclosing one is entirely your own calculation in your own checkout. The [Consumer Fee Passthrough](/faqs-and-troubleshooting/payments-faqs/consumer-fee-passthrough-for-wallet-and-crypto-tenders.md) page is guidance on how to do that and on the legal considerations. It is not a feature you enable.

You can collect a consumer fee with or without this program; the two are independent. That said, using the Rebate Program for anything other than a zero-value rebate means that in practice you are collecting one, because the only way to make `total` exceed what the merchant billed is to fold a fee into the amount before payment creation. If you build a rebate integration you are subject to the legal and compliance considerations on that page directly, including state surcharge law and per-tender restrictions, not as a "see also." Bead publishing guidance is not Bead approving your fee structure.

The pattern: calculate your consumer fee yourself and fold it into `total`. Set `merchantPortion` to the exact price the merchant billed, with nothing deducted. Set `targetRebate` to the fee amount. The merchant is settled precisely what they billed, with no net due to fees. The withheld amount is paid out to you later, net of Bead's rebate fee, on the cadence described in [Partner distributions](#partner-distributions).

**Leave headroom between your consumer fee and Bead's rebate fee.** If the consumer fee you charge runs too close to what Bead's rebate fee would be on that same transaction, `partnerNet` can land at or below zero, and the payout for that transaction is held back rather than paid. See [Bead's rebate fee](#beads-rebate-fee) above, and confirm the current rate with your Bead contact before sizing a fee schedule against it.

### Before you start

A merchant must be enrolled in the Rebate Program before it can accept a `rebate` block. Enrollment is a reviewed change to the merchant record, submitted and approved through [Update Merchant](/entity-management/merchant-management/update-merchant.md).

There is no field for this on merchant application submission — `isRebateProgramEnabled` is not part of the onboarding/application request. A merchant must be boarded first, then enrolled with the update-request call below. Nothing stops you from submitting the enrollment request immediately after boarding completes, since it's a partner-self-service call, but it is always a separate second step.

Use a partner API key. You can enroll any merchant in your own hierarchy, and you can approve your own request. Terminal API keys cannot make this change and return `403 Forbidden`.

**Step 1. Request the change.** Note the request id in the response.

```json
POST /Merchants/{merchantId}/update-requests

{
  "submit": true,
  "precedence": 100,
  "justification": "Enrolling in the rebate program",
  "changes": {
    "setRebateProgramEnabled": true
  }
}
```

**Step 2. Approve it.** The change applies immediately on approval.

```json
POST /Merchants/{merchantId}/update-requests/{requestId}/approve

{
  "reason": "Approved for rebate program"
}
```

**Step 3. Confirm.** [Get Merchant](/entity-management/merchant-management/get-merchant.md) returns `isRebateProgramEnabled: true`.

To remove a merchant from the program, send the same request with `"setRebateProgramEnabled": false`. That stops new rebate payments. Anything already taken still pays out to the partner as normal, and in-flight settlements and assessed distributions are unaffected.

> Enrollment cannot be time boxed. Setting `expiresAt` on the update request does not revert the rebate flag. Use an explicit `false` request to remove a merchant from the program.

Separately, confirm the partner payout setup described in [Partner distributions](#partner-distributions) before the first rebate payment is taken. That setup is not part of enrollment and is not validated here.

### Creating a rebate payment

Add a `rebate` object to the normal payment creation request. The endpoint and all other fields are unchanged.

Endpoint:

```http
POST https://api.test.devs.beadpay.io/Payments/crypto
```

Headers:

```http
X-Api-Key: {apiKey}
Content-Type: application/json
Accept: application/json
```

Request body:

```json
{
  "terminalId": "TERM-123",
  "merchantId": "MERCH-456",
  "requestedAmount": 100.00,
  "reference": "ORDER-4821",
  "rebate": {
    "total": 100.00,
    "merchantPortion": 90.00,
    "targetRebate": 10.00
  }
}
```

The response is the standard payment creation response. See [Create Payment](/payments/create-payment.md) for the full shape and for the terminal type rules that also apply to rebate payments, including the `customer` and `refundEmail` requirements on virtual terminals.

#### Field reference

`rebate` — Optional object. Only accepted for merchants enrolled in the Rebate Program. Omit it entirely for a standard payment.

`rebate.total` — The total amount the consumer pays. Must exactly equal `requestedAmount`.

`rebate.merchantPortion` — The exact amount to settle to the merchant daily. Settled in full with no transaction fee deducted.

`rebate.targetRebate` — The amount withheld at settlement for later distribution to the partner. Must exactly equal `total` minus `merchantPortion`.

### Why a rebate payment is rejected

All of the following return `400 Bad Request`.

| Condition                                                 | What to check                                                                                  |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `merchantPortion + targetRebate` does not equal `total`   | The core rule. Look for a rounding error, for example `90.00 + 9.99` against a `100.00` total. |
| `total` does not equal `requestedAmount`                  | Usually the ticket amount changed and only one of the two values was updated.                  |
| Only one or two of the three amounts sent                 | All or nothing. Send all three, or omit the `rebate` block entirely.                           |
| A `rebate` block sent for a merchant that is not enrolled | Confirm `isRebateProgramEnabled` on the merchant record.                                       |
| `merchantPortion` greater than `total`                    | The values are most likely transposed.                                                         |
| More than two decimal places on any amount                | Often a percentage calculated on your side and not rounded before sending.                     |

If you calculate `merchantPortion` or `targetRebate` from a percentage, round to two decimals and then derive the third value by subtraction rather than by a second percentage calculation. Deriving both independently is the most common cause of a failed identity check.

> Error responses on this endpoint are not fully uniform. Most validation failures return the standard error body, but the enrollment check returns a plain text message rather than the structured error shape. Match on the HTTP status rather than on the response shape, and log the body.

#### What is not returned

The rebate amounts you send are not echoed back on the payment creation response, the payment status endpoints, or [Payment Statuses](/payments/payment-statuses.md) tracking. Bead's rebate fee is not returned on any payment level response either.

Keep your own record of what you sent. To see rebate amounts and the fee after the fact, use the [Reporting](#reporting) endpoints below.

Payment webhooks are unchanged for rebate payments, and partner distributions do not emit webhooks.

### Settlement behavior

* The merchant is settled `merchantPortion` on the normal daily cycle, with no transaction fee.
* Nothing is billed back to the merchant later. Collection happens by withholding at settlement.
* The standard per-deposit bank transfer fee still applies to the deposit as a whole, exactly as it does on any program. It is not a rebate-specific charge, but the bank credit is the day's settlement total less that fee.

> **Small daily volumes are held more often.** A deposit is held when the day's net does not cover the bank transfer fee. Because a rebate merchant's daily net is `merchantPortion` rather than the full ticket value, a merchant with a low merchant portion reaches that threshold less often than the same merchant on standard processing, and will see held deposits more frequently. Factor this in when setting the merchant portion for low volume merchants.

Settlement and batch records include two informational fields for rebate activity:

| Field                    | Description                                                              |
| ------------------------ | ------------------------------------------------------------------------ |
| `targetRebate`           | Sum of `targetRebate` across rebate payments in the settlement or batch. |
| `rebateTransactionCount` | Number of rebate payments in the settlement or batch.                    |

Both appear on [Settlements](/settlement/settlements.md) and [Batches](/settlement/batches.md) and are available as selectable CSV columns. Merchants with no rebate activity show zero.

These are aggregates for visibility. They are not the basis of the partner payout. See the caution in [Residual Reporting](/settlement/residual-reporting.md).

### Partner distributions

Withheld rebate is paid to the partner as a single periodic bank transfer covering all of that partner's merchants together, not one payment per merchant or per transaction.

* The amount is the sum of `targetRebate` across every qualifying payment in the run, less the per payment rebate fee.
* The current schedule is monthly, on the 1st. The schedule is configuration, so a different cadence is a change request to your Bead contact rather than development work.
* Payment arrives on normal ACH timescales.

Four things must be in place before a partner can be paid, and none of them are checked at enrollment. They are checked when the payout runs, which means a gap here surfaces at the first payout rather than at setup:

1. The partner has a designated representing merchant record, which is where the funds are sent and where the partner's contracted rates are read from.
2. That merchant has complete bank details, with an account type of `Checking` or `Savings`.
3. That merchant has fee rules for every payment method the rebate merchants will use. Bead's fee is read per payment method, so a payment on a method with no configured rate cannot be priced and will not settle.
4. That merchant is active.

Separately, every merchant on the program must have its partner set. Confirm all of this with your Bead contact before the first rebate payment is taken.

#### Refunds (reserved)

No Bead tender currently supports a refund, so this does not come up in practice today. The behavior below is defined for when a tender that supports refunds is added, or another refund-like event occurs:

* A rebate payment that is refunded, in full or in part, before the partner payout would be excluded from that payout automatically.
* A refund that lands after the payout has gone out would be corrected on the partner's next distribution.
* A refund returns the full amount the consumer paid, which is `total`, not `merchantPortion`.

### Reporting

Two report families cover rebate activity. Both support pagination, sorting, and column selectable CSV export, and both are callable with your partner API key for your own partner or any partner beneath it. See [Rebate Reports](/reporting/rebate-reports.md) for the full reference.

These reports are the only place rebate amounts and Bead's rebate fee are readable after payment creation.

#### Distribution status values

| Status      | Meaning                                          |
| ----------- | ------------------------------------------------ |
| `assessed`  | Calculated and awaiting payout.                  |
| `paying`    | Payout in progress.                              |
| `paid`      | Paid to the partner.                             |
| `blocked`   | Held for Bead review. Not retried automatically. |
| `cancelled` | Voided.                                          |

A blocked distribution reports one of the following reasons: `partnerNetNotPositive`, `representingMerchantNotFound`, `representingMerchantInactive`, `missingBankDetails`, `unsupportedBankAccountType`, `originationRejected`, `originationAmbiguous`, `payoutReturned`.

`partnerNetNotPositive` means the distribution as a whole netted to zero or less. Individual underwater payments do not trigger it; they are netted into the total. See [Bead's rebate fee](#beads-rebate-fee).

If a distribution is blocked, contact your Bead integration contact. Blocked distributions are not retried automatically.

### Troubleshooting

**A payment is rejected with `400`** Work through the table in [Why a rebate payment is rejected](#why-a-rebate-payment-is-rejected). The identity check and the `total` versus `requestedAmount` check account for most cases.

**The merchant's settlement does not match `merchantPortion`** Confirm the payment carried a `rebate` block and that the merchant was enrolled at the time of creation. A payment created before enrollment is processed as a standard payment. Check the [rebate transaction report](/reporting/rebate-reports.md) for the payment to see the amounts as they were recorded. Raise it with your Bead contact if the amounts still do not line up.

**The merchant's deposit did not arrive** Check whether the day's net cleared the bank transfer fee. Rebate merchants settle at `merchantPortion` rather than the full ticket value, so low volume days fall below that threshold more easily. See [Settlement behavior](#settlement-behavior).

**Enrollment returns `403`** You are using a terminal API key. Enrollment requires a partner API key with the merchant in its hierarchy.

**A partner has not been paid when expected** Check the three prerequisites in [Partner distributions](#partner-distributions) first. A missing representing merchant, incomplete bank details, or an inactive merchant record are the most common causes, and none of them fail at enrollment.

**Payments are accepted but the partner earns nothing** The rebate is not covering the rebate fee. See [Bead's rebate fee](#beads-rebate-fee) and revisit the fee structure with your Bead contact before scaling volume.

### Next steps

* [Create Payment](/payments/create-payment.md) for the full payment creation contract
* [Rebate Reports](/reporting/rebate-reports.md) for transaction detail and partner distribution reconciliation
* [Settlements](/settlement/settlements.md) and [Residual Reporting](/settlement/residual-reporting.md) for reconciliation
* [Update Merchant](/entity-management/merchant-management/update-merchant.md) for the enrollment change


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.bead.xyz/payments/rebate-program.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
