Skip to content

Crypto invoicing, equivalents and payments

Outcome
Configure wallets, opt into crypto equivalents or crypto-priced documents, and record crypto payments.
Prerequisites
An entity and API key.
You'll use
Entity key, or account key plus entity_id.

Space Invoices supports crypto in three independent ways:

  1. Crypto equivalents — show a read-only crypto amount alongside a normal fiat invoice. The document stays invoiced and settled in its fiat currency.
  2. Crypto invoicing — price a document’s own currency_code directly in a crypto asset (for example BTC); no opt-in through the API. Tax and totals are still converted to the entity’s fiat currency for reporting.
  3. Crypto payments — record a payment with type: "crypto". It is opt-in: available once crypto invoicing or crypto equivalents is enabled for the entity, or on a document priced in crypto.

None of these require a specific wallet or blockchain integration — Space Invoices does not watch, verify, or reconcile on-chain transactions. It stores the wallet address you configure and prints it; you settle and confirm payment yourself.

Supported Assets

CodeNameDecimals
BTCBitcoin8
ETHEther8
SOLSolana6
USDCUSD Coin2
USDTTether2

Amounts in a crypto currency are always rounded to that asset’s decimals, not the usual 2 decimal places — a BTC-priced invoice keeps up to 8 decimal places.

1. Configure Wallets

Wallet addresses live on the entity, one per asset code, and are looked up by code wherever a wallet needs to be shown (crypto equivalents, the issuer snapshot on a crypto-priced document). You never enter a wallet per document.

Configure crypto walletstypescript
await sdk.entities.update(entity.id, {
  settings: {
    crypto_wallets: [
      { code: "BTC", address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", network: "Bitcoin" },
      { code: "USDC", address: "0x71C7656EC7ab88b098defB751B7401B5f6d8976", network: "Ethereum" },
    ],
  },
});

Rules:

  • up to 5 wallets, one per asset code (no duplicates)
  • address is 20–128 characters, letters/digits/colons only
  • network is an optional free-text label printed next to the address (for example "Ethereum", "Solana", "Tron")
  • settings keys merge per top-level key, so this call does not touch any other settings — send only crypto_wallets
  • send crypto_wallets: null to clear all configured wallets

2. Crypto Equivalents on Fiat Documents

Turn on settings.crypto_equivalents to add a read-only crypto amount to invoices, advance invoices, and estimates. Credit notes and delivery notes always report crypto_equivalents: null. The document itself is unaffected — it is still created, finalized, and paid in its own fiat currency_code.

Enable crypto equivalentstypescript
await sdk.entities.update(entity.id, {
  settings: {
    crypto_equivalents: { enabled: true, codes: ["BTC", "USDC"] },
  },
});
  • codes takes up to 3 unique asset codes, and needs at least one when enabled is true
  • a document denominated in crypto (see below) never gets a crypto_equivalents value — it would be redundant

Each crypto_equivalents entry looks like this on a EUR invoice with a €1,220.00 total, BTC at 74,462.51 EUR/BTC:

{
"code": "BTC",
"amount": 0.01638408,
"rate": 74462.51,
"quote_currency": "EUR",
"source": "auto",
"date": "2026-01-15T00:00:00.000Z",
"wallet_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"network": "Bitcoin"
}
  • amount is the document total divided by rate, rounded to the asset’s own decimals
  • when a configured asset’s rate cannot be resolved, that asset is silently skipped; if none resolve, crypto_equivalents is null (the document is still created)
  • wallet_address/network are looked up from crypto_wallets at the time the equivalent is computed

What happens on update:

  • changing currency_code or date re-resolves rates for the new currency/date under the entity’s current settings — if crypto_equivalents is now disabled, this naturally resolves to null
  • changing only the line items rescales the existing equivalents using their already-stored rate (no new rate lookup)
  • any other change (a note, for example) leaves crypto_equivalents untouched

3. Invoices Priced in Crypto

A document’s own currency_code can be a crypto asset code (BTC, ETH, SOL, USDC, USDT), so the document is created, issued, and its balance tracked in that asset directly. No opt-in is needed through the API: it works for every entity except UK entities. (settings.crypto_invoicing is only a web-app preference that shows crypto currencies in the document currency picker.) Create the document with a crypto currency_code:

Invoice priced in BTCtypescript
const _invoice = await sdk.invoices.create({
  currency_code: "BTC",
  customer: { name: "Crypto Customer" },
  items: [{ name: "Service", quantity: 1, price: 0.01, taxes: [{ rate: 22 }] }],
});

For a €0.01 BTC line at 22% tax, with BTC at 74,462.51 EUR/BTC, the response looks like:

{
"currency_code": "BTC",
"total": 0.01,
"total_with_tax": 0.0122,
"total_converted": 744.63,
"total_with_tax_converted": 908.44,
"exchange_rate": { "rate": 74462.51, "quote_currency": "EUR", "source": "auto" },
"taxes": [{ "base": 0.01, "amount": 0.0022, "base_converted": 744.63, "amount_converted": 163.82 }],
"issuer": {
"crypto_wallet": { "code": "BTC", "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "network": "Bitcoin" }
},
"crypto_equivalents": null
}

Applies to invoices, advance invoices, estimates, credit notes, and delivery notes; POST /documents/calculate previews the same numbers before you create anything. All amounts on the document (total, item totals, total_due, payments) stay at the asset’s own precision; only the *_converted fields and exchange_rate are in the entity’s fiat currency, for reporting.

issuer.crypto_wallet is a snapshot of the wallet configured for that asset code at creation/currency-change time — change crypto_wallets later and existing documents keep the old snapshot until their currency_code changes again.

Rejected (422)

ConditionYou’ll see
Entity country_code is GB”UK entities cannot issue documents in crypto assets; HMRC treats cryptoassets as non-money — issue in GBP”
No resolvable exchange rate for the asset/date”Exchange rate is unavailable for this crypto asset and date. A crypto-currency document must have a resolvable local-currency value.”

Nothing is persisted when any of these fire.

4. Recording Crypto Payments

Record a payment with type: "crypto" on a document priced in crypto, or on a fiat document when the entity has enabled settings.crypto_invoicing or settings.crypto_equivalents. Otherwise the API rejects it with 422 and cause.code crypto_payment_type_not_enabled (the same applies when changing an existing payment’s type to crypto, and to payments sent inline when creating a document). A document priced in crypto always accepts it, even if the setting is later switched off. Use reference for the on-chain transaction hash; amount is in the document’s own currency (crypto amount for a crypto-priced document, fiat amount otherwise):

Record a crypto paymenttypescript
const _payment = await sdk.payments.create({
  invoice_id: invoice.id,
  type: "crypto",
  amount: 0.0122,
  reference: "3a1b9e0c7d5f2a8b6c4d1e9f0a7b3c5d8e2f1a4b6c9d0e3f5a7b1c8d2e4f6a9b",
});

Space Invoices does not verify the transaction on-chain — recording the payment marks the document as paid the same way any other payment type does.

Compliance and Exports

A crypto-priced document (currency_code is a crypto asset) can still be reported and exported anywhere that works from its fiat-converted totals:

Works via converted (EUR/fiat) amountsNot available for crypto-priced documents (422)
FURS (Slovenia fiscalization)Peppol/UBL, XRechnung, ZUGFeRD (EN 16931-based e-invoicing)
FINA (Croatia fiscalization)France Chorus Pro / PDP e-reporting (also EN 16931-based)
e-SLOG / UJP (Slovenia)NAV Online Számla (Hungary)
Slovenian VAT ledger exports (KIR/VOD)KSeF (Poland)
Portuguese SAF-TFatturaPA / SdI (Italy)
Spreadsheet exports and reports
Minimax and QuickBooks accounting exports (booked in entity currency)

Fiscalization of crypto payments. In Slovenia (FURS) crypto is treated like cash: an invoice paid in crypto is fiscalized and cannot skip FURS (only bank-transfer or unpaid invoices can), and changing a skipped invoice’s payment to crypto is refused until it is fiscalized, exactly as for cash. A crypto-priced invoice is submitted to FURS with its EUR-converted amounts. In Croatia (FINA) every invoice is fiscalized anyway, and a crypto payment is sent with payment method (NacinPlac) O (“other”).

Crypto equivalents on a fiat document never affect any export — the underlying document is still plain fiat.

PDFs

The PDF shows the document’s own currency_code and amounts at that currency’s precision (so a BTC invoice prints BTC amounts to 8 decimals, not rounded to 2), the crypto_equivalents block when configured, and the issuer’s crypto_wallet address/network when the document currency is crypto. "crypto" is a recognized payment type on the payments list (offered in the payment forms only under the rule above).

The PDF prints the real source next to the rate rather than the API’s internal "auto"/"manual" values: crypto rates (a crypto-denominated document’s own exchange_rate and each crypto_equivalents[].rate) are printed with source “Coinbase”; fiat foreign-currency conversion rates are printed with source “ECB” (localized to a short local abbreviation on supported document locales). A manually entered rate is printed as a localized “manual rate” instead.

Payment QR codes (Slovenian UPN, EPC/SEPA and Croatian HUB3) are never generated for crypto-priced documents.

  • Entities API — PUT /entities/{id}, settings.crypto_wallets, settings.crypto_equivalents, settings.crypto_invoicing (web-app picker preference)
  • Invoices API — POST /invoices, POST /documents/calculate
  • Payments API — POST /payments, type: "crypto"
  • Invoices Guide — base invoice lifecycle