Skip to content
Integral Help Center home
Integral Help Center home

Fireblocks CSV Import (when API data is incomplete)

In some cases, the Fireblocks API does not return every historical transaction you see in the Fireblocks UI. This can lead to gaps in Integral's transaction history, especially for older activity or certain internal transfers.

To fill these gaps, you can export transactions from Fireblocks as CSV files and run a small helper script that converts them into per-wallet CSVs ready for import into Integral.

When to use this CSV import method

Use this method if:

• You notice missing transactions in Integral compared to Fireblocks (for example, some historical withdrawals or internal vault transfers do not appear)

• Fireblocks' API returns partial data, but the CSV export from the Fireblocks UI shows the full transaction list

• You need a one-time backfill for a specific period (e.g. March–April 2026) or a specific wallet like "Trading" or "Payment"

This method does not change the live sync; it just lets you import missing transactions via CSV.

What the script does

At a high level, the script:

• Reads every Fireblocks CSV file in a folder

• Builds one CSV per Fireblocks Vault wallet (for example: Trading, Payment)

• Shows all money moving into and out of each wallet, with clear signs:

- Negative Amount = money leaving the wallet (withdrawals, internal sends)

- Positive Amount = money entering the wallet (deposits, internal receives)

• Keeps fees, counterparties, and transaction hashes intact for reconciliation

• Avoids double-counting if you accidentally include the same Fireblocks export more than once

It only creates CSVs for Fireblocks Vault wallets (your main wallets in Fireblocks). External recipients (e.g. individual names or labels like "New server") show up only as Counterparty Name inside those wallet files, not as separate files.

What the output files look like

The script creates a folder called integral_per_wallet in the same location as the script. Inside that folder, you'll see one CSV per Vault wallet, for example:

wallet_Trading.csv

wallet_Payment.csv

Each CSV has these columns:

Date – in the format YYYY-MM-DD HH:MM (e.g. 2026-04-10 10:53)

Amount – decimal number; negative for outflows, positive for inflows; no scientific notation

Symbol – asset symbol (e.g. USDC, USDT)

Fee Amount – network fee as a decimal string (never in 1e-07 format)

Fee Symbol – usually the same as the asset symbol or the network token

Counterparty Address – blockchain address on the other side of the transfer

Counterparty Name – Fireblocks label on the other side (e.g. Payment, a contact name, an exchange label)

Transaction Hash – on-chain tx hash

Memo – any Fireblocks note on the transaction

These files are structured so you can import them into Integral using the "transfers" CSV template (per wallet) or use them for your own reconciliation.

How to run the script (step-by-step)

Step 1 – Install Python and pandas

1. Make sure Python 3 is installed:

- On Windows: open Command Prompt and run python --version

- On macOS: open Terminal and run python3 --version

2. Install pandas once:

- On Windows: pip install pandas

- On macOS / Linux: pip3 install pandas

Step 2 – Prepare the folder

1. Create a folder anywhere (for example: Fireblocks_Conversion)

2. Put all Fireblocks CSV export files into this folder

- These should be the normal Fireblocks exports (semicolon ; separated)

3. Save the script into the same folder as: fireblocks_to_integral_wallets.py

So the folder contains, for example:

fireblocks_to_integral_wallets.py

fireblocks_march.csv

fireblocks_april.csv

• etc.

Step 3 – Run the script

From a terminal:

Windows:

cd C:\Users\YourName\Desktop\Fireblocks_Conversion python fireblocks_to_integral_wallets.py

macOS / Linux:

cd ~/Desktop/Fireblocks_Conversion python3 fireblocks_to_integral_wallets.py

The script will:

• Detect each CSV's delimiter (; vs ,) and load it correctly

• Ignore transactions that are not COMPLETED and CONFIRMED

• Build per-wallet rows for Vault wallets only

• Deduplicate any exact duplicates across all files (same wallet, tx hash, amount, symbol)

• Write one CSV per wallet into the integral_per_wallet folder

The terminal will print a summary, including which wallets had activity and where the files were written.

After running: next steps in Integral

Once you have the per-wallet CSVs:

  1. Validate the CSV Transactions data

  1. Open Integral and navigate to the area where CSV transaction imports are supported (e.g. Bookkeeping / Transactions import)

  2. Upload the relevant wallet file(s) such as wallet_Trading.csv or wallet_Payment.csv

  3. Confirm that the missing withdrawals, deposits, and internal transfers now appear and match what you see in Fireblocks

If something does not look right (for example, a sign is flipped or a wallet is missing), contact Integral support with the wallet CSV and the original Fireblocks row so we can adjust the mapping logic.

## Important: Transfers only

This script currently only supports the transfers format. The generated CSVs contain wallet inflows and outflows (deposits, withdrawals, and internal transfers).

If your Fireblocks data includes trades (e.g. conversions between assets, swap transactions), please contact Integral support and let us know. We can provide an updated version of the script that also generates trade-formatted CSVs.

---

Script

Copy paste the script into a file and save it as fireblocks_to_integral_wallets.py

""" Fireblocks → per-wallet CSV converter (for Integral) How to use (for non-technical users): 1. Install Python 3 (if not already installed). 2. Install the 'pandas' library: - Open a terminal / command prompt. - Run: pip install pandas 3. Put this script and all your Fireblocks CSV files in the SAME folder. 4. Double-click this script (or run "python fireblocks_to_integral_wallets.py") from that folder. What it does: - Reads every CSV in the folder (semicolon ';' or comma ',' separated). - For each successful Fireblocks transaction (COMPLETED + CONFIRMED): - Creates one row for the Source Vault wallet (negative Amount, outflow). - Creates one row for the Destination Vault wallet (positive Amount, inflow). - Only Vault wallets (e.g. Trading, Payment) get CSVs. - Named people / external wallets only appear as Counterparty, never as their own CSV. - Deduplicates across all files so the same wallet+transaction+amount+symbol only appears once. Outputs: - A folder "integral_per_wallet" containing one CSV per Vault wallet: - wallet_Trading.csv, wallet_Payment.csv, etc. Each CSV has columns: Date, Amount, Symbol, Fee Amount, Fee Symbol, Counterparty Address, Counterparty Name, Transaction Hash, Memo """ import os import glob from datetime import datetime from decimal import Decimal, InvalidOperation import pandas as pd # Output directory (created next to the script) OUT_DIR_WALLETS = "integral_per_wallet" # ===== Helper functions ===== def detect_delimiter(path: str) -> str: """ Detect whether the file uses ';' or ',' as delimiter by inspecting the header line. """ with open(path, "r", encoding="latin-1") as f: header = f.readline() if ";" in header and "," not in header: return ";" if "," in header and ";" not in header: return "," # Default to ';' if both/unclear, since Fireblocks exports usually use ';' return ";" def parse_fireblocks_datetime(s: str) -> str: """ Fireblocks example: '10 Apr 2026 10:53:50 GMT' Output: '2026-04-10 10:53' """ dt = datetime.strptime(s, "%d %b %Y %H:%M:%S %Z") return dt.strftime("%Y-%m-%d %H:%M") def to_str_decimal(v): """ Convert numbers (including scientific notation) to plain decimal strings. Example: 3.04515469111E-7 -> '0.000000304515469111' """ if v is None or v == "" or (isinstance(v, float) and pd.isna(v)): return "" try: return format(Decimal(str(v)), "f") except InvalidOperation: return str(v) def safe_float(v): try: return float(v) except (TypeError, ValueError): return 0.0 def process_fireblocks_file(path: str) -> list[dict]: """ Read one Fireblocks CSV and return a list of per-wallet rows (both Source and Destination views) for Vault wallets only. """ print(f"Processing file: {os.path.basename(path)}") sep = detect_delimiter(path) print(f" Detected delimiter: '{sep}'") # Read Fireblocks export with detected delimiter # Use latin-1 encoding to avoid UnicodeDecodeError on odd bytes fb = pd.read_csv( path, sep=sep, engine="python", encoding="latin-1", ) # Only successful transfers fb_success = fb[ (fb["Status"] == "COMPLETED") & (fb["Sub-Status"] == "CONFIRMED") ].copy() wallet_rows: list[dict] = [] for _, row in fb_success.iterrows(): date_str = parse_fireblocks_datetime(row["Date"]) # Amount and fees net_amount = row.get("Net Amount") if pd.isna(net_amount): net_amount = row.get("Amount") net_amount_f = safe_float(net_amount) symbol = row.get("Asset Symbol") or row.get("Asset") fee_amount = row.get("Network Fee", 0) or 0 fee_amount_f = safe_float(fee_amount) tx_hash = row.get("TxHash", "") note = row.get("Note", "") src_type = (row.get("Source Type") or "").strip() src_wallet = (row.get("Source") or "").strip() src_addr = row.get("Source Address") or "" dst_type = (row.get("Destination Type") or "").strip() dst_wallet = (row.get("Destination") or "").strip() dst_addr = row.get("Destination Address") or "" # Source wallet view (only if Source Type is Vault) if src_type == "Vault" and src_wallet: wallet_rows.append({ "Wallet Name": src_wallet, "Date": date_str, "Amount": to_str_decimal(-net_amount_f), # outflow "Symbol": symbol, "Fee Amount": to_str_decimal(fee_amount_f), "Fee Symbol": symbol, "Counterparty Address": dst_addr, "Counterparty Name": dst_wallet, "Transaction Hash": tx_hash, "Memo": note, }) # Destination wallet view (only if Destination Type is Vault) if dst_type == "Vault" and dst_wallet: wallet_rows.append({ "Wallet Name": dst_wallet, "Date": date_str, "Amount": to_str_decimal(net_amount_f), # inflow "Symbol": symbol, "Fee Amount": to_str_decimal(fee_amount_f), "Fee Symbol": symbol, "Counterparty Address": src_addr, "Counterparty Name": src_wallet, "Transaction Hash": tx_hash, "Memo": note, }) print(f" Successful rows in this file: {len(fb_success)}") print(f" Per-wallet rows from this file: {len(wallet_rows)}\n") return wallet_rows def main(): print("=== Fireblocks → per-wallet CSV converter ===\n") # Find all CSV files in the current folder csv_files = glob.glob("*.csv") if not csv_files: print("No CSV files found in this folder.") print("Please put your Fireblocks CSV export(s) in the same folder as this script.") return print(f"Found {len(csv_files)} CSV file(s):") for f in csv_files: print(f" - {f}") print("") all_wallet_rows: list[dict] = [] # Process each CSV file for path in csv_files: try: rows = process_fireblocks_file(path) all_wallet_rows.extend(rows) except Exception as e: print(f" Warning: Skipping {path} due to error: {e}\n") if not all_wallet_rows: print("No successful Vault wallet rows found in the CSV files.") return # Create output folder os.makedirs(OUT_DIR_WALLETS, exist_ok=True) # Build DataFrame of all per-wallet rows across all files wallet_df = pd.DataFrame(all_wallet_rows) # --- Global deduplication across all files --- # Keep a single row per wallet+transaction+amount+symbol before = len(wallet_df) wallet_df = wallet_df.drop_duplicates( subset=["Wallet Name", "Transaction Hash", "Amount", "Symbol"] ) after = len(wallet_df) print(f"Deduplicated per-wallet rows: {before} -> {after}\n") # Write one CSV per wallet wallet_names = sorted(wallet_df["Wallet Name"].unique()) print(f"Writing per-wallet CSV files to: {OUT_DIR_WALLETS}") print("Wallets:") for wallet in wallet_names: safe_wallet = wallet.replace(" ", "_") or "UNKNOWN" out_path = os.path.join(OUT_DIR_WALLETS, f"wallet_{safe_wallet}.csv") cols = [ "Date", "Amount", "Symbol", "Fee Amount", "Fee Symbol", "Counterparty Address", "Counterparty Name", "Transaction Hash", "Memo", ] wallet_df[wallet_df["Wallet Name"] == wallet][cols].to_csv(out_path, index=False) print(f" - {wallet} -> {out_path}") print("\nDone.") print("You can now upload these per-wallet files into Integral (or your downstream system).") if __name__ == "__main__": main()