Skip to content
JuicePay

JuicePay documentation

Create account

Documentation

Chains and finality

Why finality, not block time, decides when a payment is truly done.

Every disbursement JuicePay makes ends up on a specific network. Choosing well is mostly about finality, and finality is not the same thing as speed.

Block time is not finality#

A network can include your transaction in a block within a second and still reorganise that block away ten seconds later. If you credit a customer on inclusion, you have lent them money against a promise.

Finality is the point at which reverting the transaction would cost more than it is worth. Some networks give you a probabilistic answer that improves over time; others give you an explicit signal from the consensus layer.

NetworkTypical inclusionPractical finalityNotes
Base~2s~12sL2 with fast soft confirmation, L1-anchored finality
Arbitrum~1s~13sSame L2 caveat as Base
Solana~0.4s~13sOptimistic confirmation, then hardened
Ethereum~12s~15 minTreat as a settlement rail, not an interaction rail
Polygon~2s~30sCheckpoint interval dominates
Tron~3s~1 minVery cheap for high-volume small payments

JuicePay tracks both the inclusion event and the finality event internally. The status you receive reflects the one your configuration cares about.

What "settled" means here#

By default a resource becomes succeeded at finality, not at inclusion. You can opt into earlier announcement for use cases where speed matters more than reorg safety:

json
{
  "settlement_confidence": "included"
}

With included, you will receive payment_intent.succeeded early. If the transaction is later reorganised away, you receive payment_intent.reverted and the ledger entries are reversed. This is a deliberate trade: it is appropriate for digital goods delivered instantly, and inappropriate for anything you ship physically.

If you cannot describe how your system would undo a delivered order, do not use included.

Route selection#

When you ask for a payout, JuicePay picks a route. The inputs are:

  • the recipient's declared chain, if any;
  • current network cost for the transfer in question;
  • the asset's availability on each candidate chain;
  • your own chain preferences and blocklists.

You can influence the decision without taking it over entirely:

json
{
  "routing": {
    "prefer_chains": ["base", "arbitrum"],
    "avoid_chains": ["ethereum"],
    "max_network_fee": "1.25",
    "allow_bridging": true
  }
}

allow_bridging: false restricts you to chains where the asset is already held, which removes bridge exposure at the cost of sometimes paying more in consolidation later.

Gas and fee sponsorship#

Recipients should not need a native token to receive value. JuicePay sponsors network fees on outbound legs, so a payout arrives whole. The cost appears as a separate debit ledger entry, which keeps fee accounting clean and auditable.

Confirmations you can trust#

Every transfer carries its transaction hash and the chain it landed on. Verify independently if you want to:

bash
curl -s "$JUICEPAY_URL/v1/payouts/po_4bW9xK" \
  -H "Authorization: Bearer $JUICEPAY_KEY" | jq '.legs[] | {chain, tx_hash, confirmations}'