---
title: "Payout quality metrics: realized slippage, quote expiry rate, and re-quote delta"
seoTitle: "Payout quality metrics: slippage, expiry, re-quote delta"
description: "Five metrics for a quote-based payout flow: realized slippage, expiry rate, re-quote delta, delivery success, and time to settle, with formulas and a log."
date: "2026-10-12"
updated: "2026-10-12"
category: "payments"
author: "BlindPay Team"
faq:
  - q: "What metrics should I track for payout quality?"
    a: "Track five per corridor: realized slippage (delivered vs quoted amount), quote expiry rate (quotes that lapse before the user confirms), re-quote delta (how much the amount moves between an expired quote and its replacement), delivery success rate (completed payouts over all finished payouts), and time to settle (execution to completion, at the median and 90th percentile)."
  - q: "What is realized slippage on a payout?"
    a: "Realized slippage is the gap between the amount a quote promised the recipient and the amount that actually arrived, in basis points: (quoted receiver_amount minus delivered amount) divided by quoted receiver_amount, times 10,000. On a binding quote executed before it expires, it should be zero on every payout. Any non-zero value is worth a support ticket."
  - q: "What is a good quote expiry rate?"
    a: "There is no universal number, because it depends on your screen flow. As a starting point, aim for fewer than 1 in 10 quotes expiring on a single confirmation screen, then set your own baseline after a few weeks. A rising expiry rate usually means quotes are fetched too early, or the confirmation flow has too many steps."
  - q: "What does a large re-quote delta mean?"
    a: "It means the market moved during the quote window. Re-quote delta compares an expired quote with its replacement for the same inputs. Small deltas on liquid corridors are normal. Large or growing deltas on one corridor point to volatility, and they are a signal to fetch quotes later in the flow and to warn users when the new amount changes."
  - q: "Which webhook events do I need to measure payout quality?"
    a: "At BlindPay, payout.new fires when a payout is created and the source funds are captured, payout.update fires on intermediate steps, including a move to failed, and payout.complete fires when a payout is confirmed at the destination or refunded. Read the status field on every event to classify the outcome instead of relying on the event name alone."
---

Payout quality comes down to five numbers per corridor: realized slippage, quote expiry rate, re-quote delta, delivery success rate, and time to settle. On a binding quote, realized slippage should be zero. The other four tell you whether your screen flow, your corridors, and your provider are doing what they promised.

**Key takeaways**

- Realized slippage on a binding quote executed inside its window should be zero, every time.
- Expiry rate measures your UX; re-quote delta measures the market; delivery success and time to settle measure the rails.
- One event log row per quote, keyed by `quote_id`, is enough to compute all five.
- Classify payout outcomes by the `status` field on each webhook, not by the event name.
- Report time to settle as a median and a 90th percentile per rail. Averages hide the slow tail.

## Why measure payout quality at all?

Because a quote-based flow can fail quietly. A user sees one number, confirms, and either gets that number or does not. If you only track volume and revenue, you will not notice a corridor where one confirmation in five expires, or a rail whose slow tail doubled last month.

The approach borrows from site reliability engineering. Google's SRE book frames service quality as [indicators, objectives, and agreements](https://sre.google/sre-book/service-level-objectives/): pick a few metrics users care about, set a target for each, and decide in advance what you do when you miss it. The five metrics below are those indicators for payouts.

They extend the three checks in [how live quotes turn the quoted rate into the rate you get](/resources/more/stablecoin-fx-slippage-live-quotes). Terms follow the [on/off-ramp liquidity glossary](/resources/more/onramp-offramp-liquidity-glossary).

## Which five metrics matter, and how do you calculate them?

Each metric has one formula, a starting target, and a meaning when it goes wrong. Targets below are starting points; set your own after a few weeks of data.

| Metric | Formula | Starting target | A bad number tells you |
| --- | --- | --- | --- |
| Realized slippage | (quoted receiver_amount - delivered amount) / quoted receiver_amount x 10,000 | 0 bps on a binding quote | The quote was not binding, or a fee landed outside the quote |
| Quote expiry rate | quotes expired before confirm / quotes shown | Under 10% on a single confirm screen | Quotes are fetched too early, or the flow is too long |
| Re-quote delta | (new receiver_amount - old receiver_amount) / old receiver_amount x 10,000 | Within the corridor's normal range | The corridor is volatile right now |
| Delivery success rate | completed / (completed + failed + refunded) | Above 99% on established corridors | Bad recipient data, compliance holds, or a rail issue |
| Time to settle | completed_at - executed_at, p50 and p90 per rail | Within the rail's expected window | A rail, a review step, or a cut-off is slowing payouts |

A few rules for reading them:

- **Realized slippage is binary in practice.** On a binding quote executed before `expires_at`, the recipient gets the quoted `receiver_amount`. A non-zero value is not "a bit of noise", it is a finding.
- **Re-quote delta needs the same inputs.** Compare quotes with the same amount, currency side, fee setting, and destination. Otherwise you are measuring your own changes.
- **Delivery success excludes payouts still in flight.** Count only payouts that reached a terminal status: `completed`, `failed`, or `refunded`.
- **Time to settle is per rail.** Pix and SPEI settle in minutes, RTP is instant, and ACH, TED, and SEPA take about one to two business days, per BlindPay's [cut-off times reference](/docs/kb/cut-off-times). Blending them makes every number meaningless.

The policy benchmark for speed is the G20 roadmap. The [Financial Stability Board's targets](https://www.fsb.org/2021/10/targets-for-addressing-the-four-challenges-of-cross-border-payments-final-report/) aim for 75% of retail cross-border payments to make funds available within one hour of initiation, and the rest within one business day, by end-2027. Your p50 and p90 per rail show where you stand against that.

## What does a week of numbers look like?

**Illustrative example.** A marketplace pays sellers in Brazil and Mexico. One week of data:

- Quotes shown: 4,000. Confirmed and executed: 3,250. Expired before confirm: 560. Abandoned without expiring: 190.
- Expiry rate: 560 / 4,000 = 14%.
- Re-quotes after expiry: 480. Average re-quote delta: 9 bps on BRL, 6 bps on MXN.
- Payouts finished: 3,240 completed, 6 failed, 4 refunded. Delivery success: 3,240 / 3,250 = 99.69%.
- Realized slippage: 0 bps on all 3,240 completed payouts.
- Time to settle over Pix: p50 3 minutes, p90 11 minutes.

What to do with it. The 14% expiry rate is above the starting target, so look at the screen: the quote is probably fetched when the payout form opens, not when the user reaches the confirm step. Moving the quote request later is the cheapest fix. The delivery success rate is healthy; the 10 failures and refunds go to a weekly review of recipient bank details. [Common stablecoin payout mistakes](/resources/more/stablecoin-payout-mistakes) lists the usual causes.

## What should the event log store?

One row per quote, keyed by `quote_id`, updated as the payout moves. This is enough to compute all five metrics.

| Field | Source | Used for |
| --- | --- | --- |
| `quote_id` | Quote response (`qu_...`) | Primary key |
| `requote_of` | Your app: the expired `quote_id` this one replaced | Re-quote delta |
| `corridor` | Your app: currency and rail | Grouping |
| `quoted_sender_amount`, `quoted_receiver_amount` | Quote response `sender_amount`, `receiver_amount` | Slippage, re-quote delta |
| `commercial_quotation`, `blindpay_quotation` | Quote response | Spread and cost tracking |
| `quote_created_at` | Your clock when the response arrives | Expiry analysis |
| `expires_at` | Quote response, epoch milliseconds | Expiry rate |
| `confirmed_at` | Your clock when the user confirms | Expiry rate, time on screen |
| `payout_id`, `executed_at` | Payout response (`po_...`) and your clock | Time to settle |
| `status` | Latest payout webhook | Delivery success |
| `completed_at` | Completion time from the payout's tracking objects | Time to settle |
| `delivered_amount` | Recipient confirmation or bank statement, where you have it | Realized slippage |

A sample row:

```json
{
  "quote_id": "qu_000000000000",
  "requote_of": null,
  "corridor": "BRL_pix",
  "quoted_sender_amount": 100000,
  "quoted_receiver_amount": 537300,
  "commercial_quotation": 5.4,
  "blindpay_quotation": 5.373,
  "quote_created_at": "2026-10-12T14:00:02Z",
  "expires_at": 1791813902000,
  "confirmed_at": "2026-10-12T14:01:15Z",
  "payout_id": "po_000000000000",
  "executed_at": "2026-10-12T14:01:16Z",
  "status": "completed",
  "completed_at": "2026-10-12T14:04:40Z",
  "delivered_amount": 537300
}
```

Two traps. `expires_at` is epoch milliseconds, not seconds; divide by 1,000 only if your date library expects seconds. And amounts are integers in minor units, so 537300 means R$5,373.00.

## How do webhooks feed the log?

Webhooks update the `status` and timestamps without polling. BlindPay sends three payout events, documented in the [webhook events reference](/docs/learn/webhooks-events):

1. `payout.new`: the payout is created and the source funds are captured. Set `payout_id` and `status`.
2. `payout.update`: the payout moves through an intermediate step, such as document checks, manual review, or the bank send. A payout that reaches `failed` arrives here too.
3. `payout.complete`: the payout is confirmed at the destination or refunded.

So the rule is simple: on every payout event, read the `status` field and write it to the row. Classify `completed`, `failed`, and `refunded` as terminal from the status, never from the event name alone. That keeps delivery success correct whichever event carried the change.

Verify every webhook signature before trusting it, and process events idempotently, since the same event can arrive twice. [Stablecoin webhooks and reconciliation](/resources/more/stablecoin-api-webhooks-reconciliation) covers both, and [stablecoin payout statuses explained](/resources/more/stablecoin-payout-statuses-explained) covers what each status means for the recipient.

## What should the dashboard show?

Three rows, read top to bottom in under a minute.

- **Row 1, health tiles.** Five numbers for the last 7 days, each against its target: realized slippage (should read 0 bps), expiry rate, average re-quote delta, delivery success rate, and Pix or SPEI p90 time to settle.
- **Row 2, per-corridor trends.** One line chart per metric, split by corridor, over 90 days. Expiry rate and re-quote delta on the same time axis, so you can see when volatility drove expiries.
- **Row 3, exceptions.** A table of payouts that broke a rule: any non-zero realized slippage, any payout past its rail's p90, and every `failed` or `refunded` payout with its reason.

Alert on two things only: any non-zero realized slippage, and a delivery success rate that drops below target for a corridor. Everything else is a weekly review.

When an expired quote triggers a re-quote in your code, log the link between the two ids. [How to handle expired quotes in TypeScript and Python](/resources/more/handle-expired-quotes-typescript-python) shows the retry pattern, and [cost per delivered dollar](/resources/more/cost-per-delivered-dollar) turns the same log into an all-in cost per corridor. For who absorbs the market move while a quote is open, see [who carries FX risk in a stablecoin payout](/resources/more/who-carries-fx-risk-stablecoin-payout).

## How does BlindPay help you measure this?

Every BlindPay quote returns the fields the log needs: `id`, `expires_at`, `commercial_quotation`, `blindpay_quotation`, `sender_amount`, `receiver_amount`, and the fee lines. Payout quotes lock the rate and fees for 5 minutes by default, and an expired quote is rejected instead of executed at a new rate, so realized slippage on BlindPay payouts executed in time is designed to be zero.

Payout webhooks are signed and carry the payout's status and tracking objects. If a payout cannot be delivered after the stablecoins are collected, BlindPay refunds them to the quote's refund wallet, or to the sending wallet when none is set; on Pix and other non-USD local rails the refund is automatic, while USD payouts and payouts whose review times out are refunded after an operator review.

## What to do next

Add the event log table to your database, write one row per quote, and backfill a week of payouts. Then compute the five metrics per corridor and set your first targets. The [payout quotes docs](/docs/payout-quotes) list every field the log reads.

*This article is general information, not legal, tax, or financial advice.*
