Deposit webhooks

Notifications for a payin, from the moment the transfer is seen on-chain until the amount is available in your balance.

Partial payments

A deposit is marked completed, and payment_detected / payment_confirmed are sent, once received_amount reaches minimum_payment percent of crypto_amount. minimum_payment is set per account; below 100 the customer may have paid less than the invoice. Before delivering, compare data.received_amount with data.crypto_amount (both in data.crypto_currency) and decide what to do with the difference.

payment_detectedPayment detected

The transaction appeared on the network and the payin is completed, but this is not the final status. funds_available is false and finality_status is pending_finality while the block can still be reorganised. If you need to move faster, you may release the product on this notice. The amount is held and is not part of the spendable balance until the network reaches the confirmations required.

Releasing the product at this stage is your decision. A payout of that amount is refused until payment_confirmed. To this day, no payment detected by Bifrost has been reversed; see payment_reversed.

json
{
  "data": {
    "status": "success",
    "wallet": "0xDeaD0000000000000000000000000000000000a1",
    "network": "BinanceSmartChain",
    "paid_with": [
      {
        "amount": "25.000000000000000000",
        "currency": "USDT"
      }
    ],
    "created_at": "2026-03-01 12:00:00",
    "cross_token": false,
    "fiat_amount": "25.00",
    "network_fee": "0.00000500",
    "confirmed_at": null,
    "percent_rate": "0.50",
    "reference_id": "11111111-1111-4111-8111-111111111111",
    "transactions": "[\"0xabc0000000000000000000000000000000000000000000000000000000000def\"]",
    "confirmations": null,
    "crypto_amount": "25.00000000",
    "customer_info": "customer@example.com",
    "fiat_currency": "USD",
    "is_duplicated": false,
    "crypto_currency": "USDT",
    "finality_status": "pending_finality",
    "funds_available": false,
    "is_wallet_fixed": false,
    "received_amount": "25.00000000",
    "reversal_reason": null,
    "internal_reference": "22222222-2222-4222-8222-222222222222",
    "received_amount_fiat": "25.00",
    "estimated_release_seconds": null,
    "received_amount_fiat_current": "25.00"
  },
  "event": "payment_detected",
  "timestamp": "2026-03-01 12:02:00"
}

payment_confirmedPayment confirmed

The block is final. funds_available is true and the amount is available in your balance. Credit the customer for good on this event.

json
{
  "data": {
    "status": "success",
    "wallet": "0xDeaD0000000000000000000000000000000000a1",
    "network": "BinanceSmartChain",
    "paid_with": [
      {
        "amount": "25.000000000000000000",
        "currency": "USDT"
      }
    ],
    "created_at": "2026-03-01 12:00:00",
    "cross_token": false,
    "fiat_amount": "25.00",
    "network_fee": "0.00000500",
    "confirmed_at": null,
    "percent_rate": "0.50",
    "reference_id": "11111111-1111-4111-8111-111111111111",
    "transactions": "[\"0xabc0000000000000000000000000000000000000000000000000000000000def\"]",
    "confirmations": null,
    "crypto_amount": "25.00000000",
    "customer_info": "customer@example.com",
    "fiat_currency": "USD",
    "is_duplicated": false,
    "crypto_currency": "USDT",
    "finality_status": "final",
    "funds_available": true,
    "is_wallet_fixed": false,
    "received_amount": "25.00000000",
    "reversal_reason": null,
    "internal_reference": "22222222-2222-4222-8222-222222222222",
    "received_amount_fiat": "25.00",
    "estimated_release_seconds": null,
    "received_amount_fiat_current": "25.00"
  },
  "event": "payment_confirmed",
  "timestamp": "2026-03-01 12:03:00"
}

payment_reversedPayment reversed

Rest assured: to this day, no payment received by Bifrost has ever been reversed.

This notice exists only because of L2 networks such as Arbitrum, Optimism and Base. On them, a payment is detected as soon as it enters an L2 block (payment_detected), within seconds, and becomes final when that block is finalized on the main network (payment_confirmed), a few minutes later. In theory, a transaction can be undone in that window. It is extremely rare, but since the possibility exists, we document it.

If it happens, the credit of that deposit is removed from the balance, data.status is reversed and reversal_reason says why. From then on, check-payin and list-payin also return status reversed.

If you release the product only on payment_confirmed, this notice does not affect you. If you release it on payment_detected, link this notice to the order by internal_reference.

json
{
  "data": {
    "status": "reversed",
    "wallet": "0xDeaD0000000000000000000000000000000000a1",
    "network": "BinanceSmartChain",
    "paid_with": [
      {
        "amount": "25.000000000000000000",
        "currency": "USDT"
      }
    ],
    "created_at": "2026-03-01 12:00:00",
    "cross_token": false,
    "fiat_amount": "25.00",
    "network_fee": "0.00000500",
    "confirmed_at": null,
    "percent_rate": "0.50",
    "reference_id": "11111111-1111-4111-8111-111111111111",
    "transactions": "[\"0xabc0000000000000000000000000000000000000000000000000000000000def\"]",
    "confirmations": null,
    "crypto_amount": "25.00000000",
    "customer_info": "customer@example.com",
    "fiat_currency": "USD",
    "is_duplicated": false,
    "crypto_currency": "USDT",
    "finality_status": "reorged",
    "funds_available": false,
    "is_wallet_fixed": false,
    "received_amount": "25.00000000",
    "reversal_reason": "reorg",
    "internal_reference": "22222222-2222-4222-8222-222222222222",
    "received_amount_fiat": "25.00",
    "estimated_release_seconds": null,
    "received_amount_fiat_current": "25.00"
  },
  "event": "payment_reversed",
  "timestamp": "2026-03-01 12:04:00"
}

When detection is already final

On some networks the payment is final as soon as it is detected. payment_confirmed is then sent right after payment_detected; payment_detected already carries finality_status final, and payment_confirmed may carry finality_status null. Decide from event and funds_available: not every payment_detected holds the amount.

Receipt fields

FieldTypeDescription
funds_availablebooleanfalse while the amount is held. true when it can be withdrawn.
finality_statusstring | nullpending_finality while confirmations are still running, final when the block is settled, reorged when the deposit was undone. Can be null on a payment_confirmed for a payment that was final on detection.
confirmationsnumber | nullReserved for the confirmation count. Currently always null; do not rely on it.
estimated_release_secondsnumber | nullReserved for an estimate of the wait until release. Currently always null; do not rely on it.
reversal_reasonstring | nullWhy the credit was removed. Null on payment_detected and payment_confirmed.
received_amountstringCrypto amount credited on the receipt.
received_amount_fiatstringFiat value of the received amount at the invoice rate.
received_amount_fiat_currentstringFiat value at the rate when the webhook was built. Falls back to the invoice rate if the live price is unavailable.
cross_tokenbooleantrue when the customer paid in a token other than the invoice token.
paid_witharrayTokens actually received on-chain. Each item has currency and amount.
is_wallet_fixedbooleantrue when the deposit landed on a fixed address.
is_duplicatedPayin Only

true when Bifrost created this payin itself, for a payment that did not match an open payin: an extra payment to an address whose payin was already completed, or a payment on a different network from the invoice. It is a new payin with its own internal_reference and a reference_id generated by Bifrost. The amount is credited to your balance, and the notice goes to the webhook_url of the original payin.

When is_duplicated is true, reference_id is not one of yours. Link the payment to your order with customer_info or wallet. The payin is also returned by List Payins and Check Specific Payin.

customer_info

Your own identifier for the customer, such as a user ID, e-mail or order ID. It is returned in webhooks and lists, so you can tell whose transaction it is, including payins Bifrost creates on its own (additional payments and fixed-address deposits), whose reference_id is generated by Bifrost.