Skip to content

Quotes & rounding

Every payment intent is denominated in fiat (EUR, USD, BRL or GBP). Before the customer pays, that amount has to become an exact amount of a crypto asset.

Live payments are processed through the platform’s Bitcart account. When the checkout opens the Bitcart invoice (POST /v1/public/checkout-sessions/{id}/processor-invoice), Bitcart prices the intent’s fiat amount in every accepted asset. Each entry of the session’s processor.methods carries:

  • amount — the exact decimal amount to send in that asset;
  • rate — the exchange rate Bitcart used (invoice currency per unit of the asset);
  • address and payment_url — where to pay, and a wallet URI for QR codes;
  • divisibility and, for tokens, contract.

The checkout labels the rate as Bitcart’s exchange rate. GRYPHEM PAY does not set it, does not add a spread to it and does not offer it as a price reference. The invoice expires with the intent’s payment window.

In watch-only processing (see Wallets; this platform does not use it for payments), the gateway itself issues a quote when the customer chooses a network and asset: an immutable, versioned conversion from your fiat amount to an exact asset amount, locked for a limited time.

{
"id": "qt_01J…",
"object": "quote",
"network_id": "bitcoin:mainnet",
"asset_id": "btc",
"asset_symbol": "BTC",
"decimals": 8,
"fiat_amount": "59.90",
"fiat_currency": "EUR",
"asset_amount": "0.00099834",
"asset_amount_base_units": "99834",
"rate": "60000.00",
"spread_bps": 0,
"rounding_policy": "ceil_to_asset_base_unit",
"required_confirmations": 3,
"status": "active",
"network_fee_paid_by": "customer",
"platform_fee_billed_separately": true
}

(Abridged; the values above are illustrative and are not a price.)

The asset amount is computed with exact rational arithmetic and rounded up to the next base unit (satoshi, token unit), so the merchant never receives less than the invoiced value because of rounding:

units = ceil( fiat_amount / rate × 10^decimals × (1 + spread_bps / 10 000) )
59.90 / 60000 × 10^8 = 99833.33… → 99834 sats

No step uses binary floating point. If the division is exact, nothing is added.

The design requires a primary market feed plus a secondary sanity source, rejects stale prices and prices that deviate beyond a limit, and fails closed: if no trustworthy rate is available, no quote is issued. The quote records rate_source, secondary_source and deviation_bps as evidence.

Each quote has locked_at and expires_at. A transfer first seen before expires_at counts as on time even if it confirms later. After expiry the checkout offers Refresh quote (POST /v1/public/checkout-sessions/{id}/refresh-quote), which supersedes the old quote with a new one on the same network and address. The intent’s own expires_at still bounds how long the customer can keep paying.

  • The asset amount is what the customer must send.
  • Network fees are paid by the sender on top.
  • Platform fees are billed to the merchant separately — never deducted from the payment.