Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English | Русский | Українська | Srpski | Српски

Quick Start

Automated generation of PPDG-3R (Capital Gains Tax) and PP OPO (Capital Income Tax) reports for Interactive Brokers users in Serbia. The app automatically retrieves transaction data and creates a ready-to-upload XML file, converting all prices to dinars (RSD).

Install ibkr-porez ↗

If you use the graphical interface, configure your data (the Config button), then just use Sync to refresh data and create declarations.

If you installed GUI + CLI, you can use both the graphical interface (starts as ibkr-porez without arguments) and the command line, see below.

The GUI and CLI use the same database.

⚠️ While the GUI is running, do not use the command line, as simultaneous usage may cause database errors.

If you want to do everything via command line, continue with:

⚠️ Import is only necessary if you have more than one year of transaction history in Interactive Brokers. Flex Query allows downloading data for no more than the last year, so older data must be loaded from a full CSV export ↗.

Quickly create the required declaration

If you want to quickly create a specific declaration.

Fetch Latest Data (fetch) ↗

Generate Report (report) ↗

Upload the generated XML to the ePorezi portal (PPDG-3R section).

PPDG-3R

Automatic declaration creation

If you want to automatically receive all required declarations and track their status (submitted, paid).

Fetch latest data and create declarations (sync) ↗

Declaration Management ↗

English | Русский | Українська | Srpski | Српски

Installation

Installer (GUI + CLI)

Download the installer from the releases page:

https://github.com/andgineer/ibkr-porez/releases

The installer includes both the graphical application (GUI) and the ibkr-porez terminal command (CLI).

macOS

Download the latest .pkg file. Because the installer is not signed with an Apple certificate, macOS will block it when you try to open it.

“IBKR Porez” is damaged and can’t be opened. You should move it to the Bin.

Do not move it to the Bin. Instead:

  1. Open System Settings → Privacy & Security
  2. At the bottom of the Security section, you will see a blocked-app message. Click Open Anyway
  3. Confirm opening in the next dialog

You may need to repeat the same steps twice:

  • first when opening the downloaded installer (.dmg)
  • and again when launching the installed app from /Applications for the first time

After that, the app should launch without warnings.

Windows

Download the latest .msi file. Because the installer is not code-signed, Windows may show security warnings.

If your browser blocks the download (for example in Microsoft Edge):

  1. Open the browser downloads panel (Ctrl+J)
  2. Find the blocked .msi download
  3. Click KeepShow moreKeep anyway

When launching the installer, Windows may show Windows protected your PC:

  1. Click More info
  2. Click Run anyway

You may also see a User Account Control dialog with Unknown publisher. If the file came from the official releases page, click Yes to continue.

After installation:

  • IBKR Porez will appear in the Start Menu
  • The ibkr-porez command will be available in the terminal (you may need to restart the terminal)

Download Prebuilt Binary

You can also download binaries for your platform from the releases page:

https://github.com/andgineer/ibkr-porez/releases

The archive contains both binaries: ibkr-porez (CLI) and ibkr-porez-gui (GUI). Extract the archive and place the files somewhere in your PATH.

Install from Source

If you have the Rust toolchain installed:

cargo install ibkr-porez

English | Русский | Українська | Srpski | Српски

Usage

Configuration (config)

ibkr-porez config

Creating or modifying personal data and IBKR access settings.

You will be prompted for:

  • IBKR Flex Token: Get Token ↗
  • IBKR Query ID: Create Flex Query ↗
  • Personal ID: JMBG / EBS
  • Full Name: First and Last Name
  • Address: Registered Address
  • City Code: 3-digit municipality code. Example: 223 (Novi Sad). Code can be found in the list (see column “Šifra”). Also available in the dropdown on the ePorezi portal.
  • Phone: Phone
  • Email: Email
  • Data Directory: Absolute path to folder with data files (transactions.json, declarations.json, rates.json, etc.). Default: ibkr-porez-data in the application folder.
  • Output Folder: Absolute path to folder for saving files from sync, export, export-flex, report commands. Default: your system’s Downloads folder.

Fetch Data (fetch)

ibkr-porez fetch

Downloads latest data from IBKR and syncs exchange rates from NBS (National Bank of Serbia).

Saves them to local storage.

Import Historical Data (import)

ibkr-porez import /path/to/activity_statement.csv

Loading transaction history older than 365 days, which cannot be retrieved via Flex Query (fetch).

To create a file with transactions on the Interactive Brokers portal, see Export Full History ↗

⚠️ Do not forget to run fetch after import so the application adds maximum details at least for the last year into the less detailed data loaded from CSV.

Synchronization Logic (import + fetch)

When loading data from CSV (import) and Flex Query (fetch), the system prioritizes more complete Flex Query data:

  • Flex Query (fetch) data is the source of truth. It overwrites CSV data for any matching dates.
  • If a Flex Query record matches a CSV record semantically (Date, Ticker, Price, Quantity), it counts as an update (replacing with official ID).
  • If data structure differs (e.g. split orders in Flex Query vs “bundled” record in CSV), the old CSV record is removed, and new Flex Query records are added.
  • Completely identical records are skipped.

Sync Data and Create Declarations (sync)

ibkr-porez sync

Does the same as fetch:

  • Downloads latest transactions from IBKR via Flex Query
  • Syncs exchange rates from NBS

Then creates all necessary declarations for the last 45 days (if they haven’t been created already).

You can then Manage created declarations.

💡 If you ran sync for the first time and it created declarations that you already submitted before starting to use the application, you can quickly mark them all as paid and remove them from list output:

ibkr-porez list --status submitted -1 | ibkr-porez pay

View Statistics (stat)

ibkr-porez stat --year 2025
ibkr-porez stat --ticker AAPL
ibkr-porez stat --month 2025-01

Shows:

  • Dividends received (in RSD)
  • Number of sales (taxable events)
  • Estimated Realized P/L (Capital Gains) (in RSD)
  • Detailed breakdown by tickers or months (when using filters)

Generate Tax Report (report)

ibkr-porez report

If you don’t specify report type and period, PPDG-3R for the last complete half-year is generated by default

  • Creates ppdg3r_XXXX_HY.xml in Output Folder
  • Import this file into the Serbian Tax Administration portal (ePorezi)
  • Manually upload the file from Confirmation Document to Item 8

To select a different declaration type or time period, see the documentation

ibkr-porez report --help

Declaration Management

After creating declarations through the sync command, you can view them, change their status, and export them for upload to the tax portal.

List Declarations (list)

Shows a list of all declarations with the ability to filter by status.

# Show active declarations (default):
# draft + submitted + pending
ibkr-porez list

# Show all declarations
ibkr-porez list --all

# Filter by status
ibkr-porez list --status draft
ibkr-porez list --status submitted
ibkr-porez list --status pending
ibkr-porez list --status finalized

# Only declaration IDs (for use in pipes)
ibkr-porez list --ids-only
ibkr-porez list --status draft -1

Example usage in Linux-style:

# Submit all drafts
ibkr-porez list --status draft -1 | ibkr-porez submit

View Declaration Details (show)

Shows detailed information about a specific declaration.

ibkr-porez show <declaration_id>

Displays:

  • Declaration type (PPDG-3R or PP OPO)
  • Declaration period
  • Status (draft, submitted, pending, finalized)
  • Transaction details and calculations
  • Attached files

Submit Declaration (submit)

ibkr-porez submit <id> [<id> ...]

Marks the declaration as submitted (imported to the tax portal).

Behavior depends on declaration type:

  • PPDG-3R moves to pending after submit (waiting for tax authority assessment).
  • PP OPO after submit:
    • moves to submitted if tax is due;
    • moves directly to finalized if tax due is 0.

Pay Declaration (pay)

ibkr-porez pay <id> [<id> ...]
ibkr-porez pay <id> --tax 1234.56

Marks the declaration as finalized and stores payment date.

Option --tax lets you record tax amount during payment, without a separate assess step.

After this, it will disappear from the list shown by list (without --all)

Record Assessed Tax (assess)

# Record official tax amount from the tax authority
ibkr-porez assess <declaration_id> --tax-due 1234.56

# Record amount and immediately mark as already paid
ibkr-porez assess <declaration_id> --tax-due 1234.56 --paid

This command is mainly for PPDG-3R, where tax amount is determined by the tax authority after submission.

What it does:

  • stores official tax amount in declaration metadata;
  • with --paid, immediately moves declaration to finalized;
  • without --paid:
    • if amount is greater than zero, keeps declaration active (submitted) for later payment;
    • if amount is zero, moves declaration to finalized.

Export Declaration (export)

ibkr-porez export <declaration_id>
ibkr-porez export <declaration_id> -o /path/to/output

Copies XML and all attached files (attach) to Output Folder or to the directory specified in parameters.

Revert Declaration Status (revert)

# Revert to draft (default)
ibkr-porez revert <id> [<id> ...]

# Revert to submitted
ibkr-porez revert <id> [<id> ...] --to submitted

Reverts declaration status.

Attach File to Declaration (attach)

# Attach file
ibkr-porez attach <declaration_id> /path/to/file.pdf

# Delete attached file
ibkr-porez attach <declaration_id> <file_id> --delete
ibkr-porez attach <declaration_id> --delete --file-id <file_id>

Attaches a file to a declaration or removes an attached file from declaration storage.

For saving to declaration storage, only the file name is used (path is discarded), so names must be unique - otherwise a file with the same name will overwrite a previously uploaded file with the same name even if from a different path

💡 Attached files are copied along with the declaration XML during export

Export Flex Query (export-flex)

ibkr-porez export-flex 2025-01-15
ibkr-porez export-flex 2025-01-15 -o /path/to/output.xml
ibkr-porez export-flex 2025-01-15 -o -  # Output to stdout (for pipes)

Exports Flex Query XML file obtained during fetch or sync on the specified date.

Example usage in Linux-style:

ibkr-porez export-flex 2025-01-15 | ibkr-porez import

English | Русский | Українська | Srpski | Српски

Interactive Brokers (IBKR)

Flex Web Service

  1. Performance & Reports > Flex Queries.
  2. Click the Settings icon (gear) in “Flex Web Service Configuration”.
  3. Enable Flex Web Service.
  4. Generate Token.
    • Important: Copy this token immediately. You will not be able to see it fully again.
    • Set expiration (recommended max - 1 year).

Flex Query

  1. Performance & Reports > Flex Queries.
  2. Click + to create a new Activity Flex Query.
  3. Name: e.g., ibkr-porez-data.
  4. Delivery Configuration (at the bottom of the page):
    • Period: Select Last 365 Calendar Days.
  5. Format: XML.

Sections to Include:

Enable the following sections and check Select All for columns.

If you don’t trust anyone 8-) instead of Select All, select at least the fields listed in Required Columns.

Transactions

Located under Trade Confirmations or Activity.

Required Columns
  • Symbol
  • Description
  • Currency
  • Quantity
  • TradePrice
  • TradeDate
  • TradeID
  • OrigTradeDate
  • OrigTradePrice
  • AssetClass
  • Buy/Sell

Cash Transactions

Required Columns
  • Type
  • Amount
  • Currency
  • DateTime / Date
  • Symbol
  • Description
  • TransactionID

Save and Get Query ID

Note the Query ID (number usually appearing next to the query name in the list).

You will need the Token and Query ID to configure ibkr-porez.

Confirmation Document

For Item 8 (Dokazi uz prijavu) of the PPDG-3R tax return, you need a PDF report from the broker. It must be attached manually on the ePorezi portal after importing the XML.

How to download the appropriate report:

  1. In IBKR go to Performance & Reports > Statements > Activity Statement.
  2. Period: Select Custom Date Range.
  3. Specify dates corresponding to your tax period (e.g., 01-01-2024 to 30-06-2024 for the first half).
  4. Click Download PDF.
  5. On the ePorezi portal, in section 8. Dokazi uz prijavu, upload this file.

Export Full History (for import command)

If you need to load transaction history for a period longer than 1 year (unavailable via Flex Web Service), export data to CSV:

  1. In IBKR go to Performance & Reports > Statements > Activity Statement.
  2. Period: Select Custom Date Range and specify the entire period since account opening.
  3. Click Download CSV.
  4. This file can be used with the import ↗ command.