Skip to content

Settlement execution

Settlement execution confirms a previously generated settlement quote and initiates the settlement process. Before executing, a valid quote must be obtained through the Settlement estimation step.

Settlement lifecycle

A settlement moves through a fixed sequence of statuses. Each status change triggers a SETTLEMENT_STATUS_CHANGE webhook.

                    ┌─────────────────────────────┐
                    │         CREATED             │
                    │  Quote generated, awaiting  │
                    │  partner confirmation       │
                    └──────────┬──────────────────┘

              ┌────────────────┼───────────────────┐
              │ confirmed                          │ not confirmed
              │ within 15 min                      │ within 15 min
              ▼                                    ▼
     ┌────────────────┐                   ┌─────────────────┐
     │   CONFIRMED    │                   │    EXPIRED      │
     │ Awaiting token │                   │ Quote no longer │
     │ transfer on-   │                   │ valid — create  │
     │ chain          │                   │ a new quote     │
     └───────┬────────┘                   └─────────────────┘

             │ tokens received

     ┌────────────────┐
     │   PROCESSING   │
     │ Settlement in  │
     │ progress       │
     └───────┬────────┘


     ┌────────────────┐
     │     SENT       │
     │ Fiat sent to   │
     │ bank account   │
     └───────┬────────┘


     ┌────────────────┐
     │    FINISHED    │
     │ Settlement     │  ← terminal state ✓
     │ complete       │
     └────────────────┘

     ┌────────────────┐
     │     ERROR      │  ← requires manual handling by BRRR support
     └────────────────┘

Status reference

StatusDescriptionTerminal?Action required
CREATEDQuote generated, awaiting partner executionNoCall Execute Settlement
CONFIRMEDQuote confirmed, awaiting on-chain token transferNoSend tokens to receiveAddress before receivedDeadline
EXPIREDQuote not confirmed within 15 minutesYesCreate a new quote — expired quotes cannot be reused
PROCESSINGTokens received, fiat settlement in progressNoNo action needed — wait for SENT
SENTFiat transferred to the designated bank accountNoNo action needed — wait for FINISHED
FINISHEDSettlement fully completeYesNo further action required
ERRORSettlement failed and requires manual reviewYesContact support@holyheld.com with the quoteId

Timing

StepTypical duration
CREATEDCONFIRMEDImmediate (partner-controlled, 15-minute window)
CONFIRMEDPROCESSINGSeconds to minutes after on-chain transfer is detected
PROCESSINGSENTMinutes to hours depending on banking rails
SENTFINISHEDTypically immediate after bank confirmation

Token transfer deadline

After executing a settlement (CONFIRMED state), you must send the token transfer to the receiveAddress before the receivedDeadline timestamp. If the deadline passes without a transfer being received, the settlement will not proceed. A new quote must be created.

Handling ERROR settlements

If a settlement reaches ERROR status:

  1. Do not retry the same quoteId — it cannot be re-executed
  2. Note the quoteId for your records
  3. Contact support@holyheld.com with the quoteId to initiate manual review
  4. Create a new quote only after confirming with BRRR support that the original transaction did not partially settle

Safe retry algorithm

If a network error prevents you from receiving the Execute Settlement response, never retry blindly. Use this sequence:

1. Call GET /partner/settlement/status/{quoteId}

2. Check the status:
   ┌──────────────────┬─────────────────────────────────────────────┐
   │ Status           │ Action                                      │
   ├──────────────────┼─────────────────────────────────────────────┤
   │ CREATED          │ Execute was not received — safe to retry    │
   │ EXPIRED          │ Quote expired — create a new quote          │
   │ CONFIRMED        │ Execute was accepted — do NOT retry execute │
   │ PROCESSING       │ Settlement in progress — do NOT retry       │
   │ SENT             │ Fiat sent — do NOT retry                    │
   │ FINISHED         │ Settlement complete — do NOT retry          │
   │ ERROR            │ Contact support — do NOT retry with same ID │
   └──────────────────┴─────────────────────────────────────────────┘

3. Only call Execute Settlement again if step 2 returns CREATED.
   For any other non-error status, the settlement has been accepted.
javascript
async function safeExecuteSettlement(quoteId, executePayload) {
  try {
    return await fetch('https://api.brrr.network/api/v4/partner/settlement/execute', {
      method: 'POST',
      headers: { 'X-Api-Key': process.env.BRRR_API_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify(executePayload),
    });
  } catch (networkError) {
    // Network error — check whether execute was received before retrying
    const statusRes = await fetch(
      `https://api.brrr.network/api/v4/partner/settlement/status/${quoteId}`,
      { headers: { 'X-Api-Key': process.env.BRRR_API_KEY } }
    );

    if (statusRes.status === 404) {
      // Quote unknown — safe to create a new quote and retry
      throw new Error('Quote not found — create a new quote');
    }

    const { payload } = await statusRes.json();

    if (payload.status === 'CREATED') {
      // Execute was not received — safe to retry
      return safeExecuteSettlement(quoteId, executePayload);
    }

    if (payload.status === 'EXPIRED') {
      throw new Error('Quote expired — create a new quote');
    }

    // Any other status means execute was accepted
    return { alreadyAccepted: true, status: payload.status };
  }
}

Confirming settlement

After calling Execute Settlement, the response contains:

  • receiveAddress — the BRRR wallet address you must send tokens to. Always use the address from this response — never cache a value from a previous settlement.
  • totalAmountIn — the exact token amount to transfer on-chain
  • receivedDeadline — Unix timestamp after which the settlement expires if no transfer is received

Once the required token amount is received on-chain, BRRR automatically advances the settlement through PROCESSINGSENTFINISHED.

Monitoring status

Poll Get Settlement Status every 15–30 seconds, or rely on SETTLEMENT_STATUS_CHANGE webhooks. Both mechanisms reflect the same state.

Webhook ordering

Settlement status webhooks may arrive out of order. Always use the timestamp field to determine whether an incoming event is more recent than your stored state. See Webhooks — Event ordering for a handler example.

Next steps

Once settlements are working end-to-end, review the Go-Live Checklist before enabling real users. When you need to remove a customer or address from monitoring, see Offboarding.