dualentry), grouped by what you’re trying to do. Each entry shows the command, what it does, its arguments and flags, and copyable examples. Every command exits with code 0 on success, 1 when it runs but fails (for example, an API error or a missing login), and 2 when the command line itself is wrong. To install the CLI and run a first command step by step, see the CLI quickstart.
The entries below are current as of dualentry-cli v0.1.18. Run dualentry <command> --help to check the version you have installed.
Set up the CLI
These commands install, upgrade, and remove the CLI, connect it to your DualEntry organization, and check its configuration and connection. This section also covers the global flags every command accepts.Install the CLI
Install the CLI on macOS or Linux with Homebrew,uv, or an install script. The uv method requires Python 3.11 or later. The install script downloads a standalone dualentry binary into /usr/local/bin (set INSTALL_DIR to choose another directory), so it doesn’t need Python; it supports macOS and Linux on x86-64, and macOS on Apple silicon.Install with Homebrew
Install with uv
Install with the install script
Upgrade the CLI
Upgrade the CLI with the same method you installed it with. The CLI checks for a newer release once a day and, while one is available, prints a notice with the upgrade command each time it runs.Upgrade with Homebrew
Upgrade with uv
Upgrade with the install script
Uninstall the CLI
Uninstall the CLI with the same method you installed it with. Before uninstalling, rundualentry auth logout to remove your stored credentials. To remove the CLI’s configuration as well, delete the ~/.dualentry directory.Uninstall with Homebrew
Uninstall with uv
Uninstall an install-script copy
Log in
dualentry-cli and prints the signed-in email and organization ID. On a machine with no usable keychain, the key is stored in ~/.dualentry/tokens.json instead, so treat that file as a credential on shared hosts.For CI/CD and other headless environments, skip auth login and set the X_API_KEY environment variable to an API key. When it’s set, it takes precedence over a stored login.Flags:--api-url(string, optional): API base URL to use instead of the default.
Log in through your browser
Authenticate with an API key instead, for CI/CD
Check your sign-in status
Prints the API URL, your email, and your organization ID, or says that you’re authenticated throughX_API_KEY. Exits with code 1 and prints Not logged in. Run: dualentry auth login when there’s no credential.Check which organization you're signed in to
View your configuration
Prints the API URL, the output format setting, and the signed-in user and organization. The CLI keeps these settings in~/.dualentry/config.toml.Show the current configuration
Use a different API host
https://api.dualentry.com, and the API key you sign in with decides which one you work against. Change the URL only to point the CLI at a different host entirely. The DUALENTRY_API_URL environment variable, when set, overrides the saved URL.Arguments:URL(string, required): Custom API base URL.
Save a custom API host
Override the host for one session
Check that the API is reachable
Prints the API URL, the API’s status, and its server time. Exits with code1 if the API can’t be reached.Check API connectivity
Use global flags
--retry, the CLI retries a request that fails with status 429, 502, 503, or 504, a 409 that carries a Retry-After header, or a network error or timeout. It waits one, two, and then four seconds between attempts, or the number of seconds in the response’s Retry-After header, capped at 60. Every request that creates or changes data carries an Idempotency-Key header, so a retried write isn’t applied twice.Flags:--version,-v(boolean, optional): Print the CLI version and exit.--retry(boolean, optional): Retry failed requests with exponential backoff, as described above.--install-completion(boolean, optional): Install tab completion for your current shell.--show-completion(boolean, optional): Print the completion script for your current shell, to copy it or customize the installation.--help(boolean, optional): Show help for the CLI, or for any command or subcommand when placed after it.
Retry rate-limited requests during a large export
Install tab completion for your shell
Print the installed version
Work with records
Most commands are resource commands: one per record type, such asinvoices, bills, or customers. Every resource command has the same subcommands, so the entries below cover all of them, with <resource> standing in for the command name. The table at the end of this section shows which subcommands and list filters each resource supports.Most transaction records, such as invoices, bills, and journal entries, have a record number, shown in the # column of list output, and an internal ID, shown in the ID column with a type prefix such as IN-12. Master data, such as customers and vendors, has only an ID.List records
--all. The filters each resource accepts vary; passing one it doesn’t support is a usage error that names the ones it does. --status takes draft, posted, or archived on transaction records.--all fetches pages of 100 records until it reaches the end, ignoring --limit but starting from --offset. It stops after 1,000 pages (100,000 records) and prints a command that resumes where it stopped. With --format json, the output is an object of the form {"items": [...], "count": N}, where count is the total number of matching records, not the number returned.Flags:--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--search,-s(string, optional): Text to search for.--status(string, optional): Return only records with this status:draft,posted, orarchived.--start-date(string, optional): Start of the date range to return, inYYYY-MM-DDformat.--end-date(string, optional): End of the date range to return, inYYYY-MM-DDformat.--company,-c(string, optional): Return only records for this company ID.--customer(string, optional): Return only records for this customer ID.--vendor(string, optional): Return only records for this vendor ID.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List posted invoices for September
List one vendor's bills
Search customers by name
Export every journal entry as JSON
Retrieve a record
--format json. On resources with record numbers, get looks the value up as a record number first and, if no record has that number, as an internal ID. get-number and get-id look it up only one way, which is safer in scripts. These subcommands accept a display prefix, so IN-5821 and 5821 work the same. On resources without record numbers, get takes the ID.Arguments:VALUE(string, required): Record number (the#column) or ID, for exampleIN-5821.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
NUMBER(string, required): Record number, shown in the#column.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
RECORD_ID(string, required): Record ID (for exampleIN-5821or5821).
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Retrieve an invoice by record number
Retrieve a journal entry by its ID
Retrieve a customer as JSON
Create a record
--file,-f(path, required): JSON file with record data.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Create an invoice from a file
Create a customer and print it as JSON
Update a record
PUT request. Pass the record number on resources that have one, including recurring records, and the ID otherwise. Unlike get, update doesn’t strip a display prefix, so pass the bare value.Arguments:RECORD_ID(string, required): Record ID.
--file,-f(path, required): JSON file with update data.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Update an invoice
Delete a record
RECORD_ID(string, required): Record ID.
Delete a recurring invoice schedule
Delete a custom field
Commands for each record type
The tables below list every resource command, grouped by area, with the subcommands it supports and the filters itslist subcommand accepts.ReceivablesPayables
Accounting
Master data
Recurring records, contracts, budgets, and workflows
Intercompany journal entries
Intercompany journal entries have three extra subcommands for drafting an entry from a file, checking it, and posting it. Use the record subcommands to list, retrieve, create, and update them.Generate an entry template
-o is short for --output.Flags:--output,-o(path, optional): File to write the template to, instead of standard output.
Write a template to a file
Validate an entry
items array isn’t empty, every debit and credit is a valid amount, total debits equal total credits, and the lines span at least two companies. --online also confirms you can access every company_id in the file. Prints ✓ Valid, or the problem and exits with code 1.Flags:--file,-f(path, required): JSON file to validate.--online(boolean, optional): Also run checks that require API access.
Validate a file offline
Validate a file and check company access
Post a draft entry
1 without changing it.Arguments:NUMBER(string, required): Record number of the draft to post.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Create an entry as a draft, then post it
Accounts and statistical journals
Theaccounts commands look up accounts in your chart of accounts, and the statistical-journals commands list, create, update, and attach files to statistical journal entries.List accounts
--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--search,-s(string, optional): Text to search for.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Search accounts
Retrieve an account
ACCOUNT_ID(integer, required): Account number.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Retrieve an account by number
List statistical journals
YYYY-MM-DD values, --updated-after and --updated-before take ISO 8601 timestamps, and the number and account filters take comma-separated lists.Flags:--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--search,-s(string, optional): Text to search for.--status(string, optional): Return only records with this status:draft,posted, orarchived.--company,-c(string, optional): Return only records for this company ID.--date-start(string, optional): Start of the journal date range to return, inYYYY-MM-DDformat.--date-end(string, optional): End of the journal date range to return, inYYYY-MM-DDformat.--period-start(string, optional): Earliest period start date to return, inYYYY-MM-DDformat.--period-end(string, optional): Latest period end date to return, inYYYY-MM-DDformat.--number(comma-separated integers, optional): Return only journals with these record numbers.--account-id(comma-separated integers, optional): Return only journals for these account IDs.--account-number(string, optional): Return only journals for these account numbers, separated by commas.--line-account-id(comma-separated integers, optional): Return only journals with lines on these account IDs.--line-account-number(string, optional): Return only journals with lines on these account numbers, separated by commas.--updated-after(string, optional): Return only journals updated after this time, as an ISO 8601 timestamp.--updated-before(string, optional): Return only journals updated before this time, as an ISO 8601 timestamp.--ordering(string, optional): API field to sort by. Prefix it with-to sort in descending order.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List journals for September
List journals that touch two accounts
Retrieve, create, or update a statistical journal
get accepts the record number with or without its SJ- prefix, and create and update read the journal from a JSON file.Get a statistical journal by number.Arguments:VALUE(string, required): Record number (the#column) or prefixed number, for exampleSJ-3.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
--file,-f(path, required): JSON file with record data.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
NUMBER(string, required): Record number of the journal to update.
--file,-f(path, required): JSON file with update data.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Retrieve a statistical journal
Create a statistical journal
Update a statistical journal
Attach files to a statistical journal
--file once per file.Arguments:NUMBER(string, required): Record number of the journal.
--file,-f(path, required, repeatable): File to attach. Repeat the flag to attach more than one file.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Attach two files
Bank matching
Thebank-match commands reconcile bank-feed transactions against DualEntry transactions.Check matching progress
unprocessed, awaiting_ai, or ai_in_progress is above zero.Flags:--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Check matching progress
List bank-feed transactions
--include-expired.List bank-feed transactions.Flags:--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--financial-account-id(integer, optional): Return only transactions for this connected bank or credit-card account ID.--matching-status(string, optional): Matching stage to filter by, such asunprocessed,ai_suggested,matched,no_match, orexcluded.--date-from(datetime, optional): Earliest transaction date to return, inYYYY-MM-DDformat.--date-to(datetime, optional): Latest transaction date to return, inYYYY-MM-DDformat.--is-posted,--not-posted(boolean, optional):--is-postedreturns only posted transactions and--not-postedonly pending ones. Omit both to return all transactions.--include-expired(boolean, optional): Include expired bank-feed rows, which are hidden by default.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
FINANCIAL_TRANSACTION_ID(integer, required): Bank-feed transaction ID frombank-match bank-transactions list.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List unprocessed rows since September 1
Show one bank-feed transaction
Review suggested matches
--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--financial-transaction-id(integer, optional): Return only suggestions for this bank-feed row ID.--suggestion-type(string, optional): Kind of suggestion:matchto pair with an existing transaction, orcreateto draft a new one.--highest-ranked(boolean, optional): Return only the top-ranked suggestion for each bank-feed row, which is what the DualEntry app shows by default.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
SUGGESTION_ID(integer, required): Suggestion ID frombank-match suggestions list.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Show the top suggestion for one bank-feed row
Confirm a match
--financial-transaction-id with exactly one of --transaction-id or --entry-id for a one-to-one or partial match, or a file for one-to-one and many-to-many matches. A file can’t be combined with the ID flags.Flags:--file,-f(path, optional): JSON file with the full match request, for one-to-one or many-to-many matches. Can’t be combined with the ID flags.--financial-transaction-id(integer, optional): Bank-feed row ID to match one-to-one. Required when you don’t pass--file.--transaction-id(integer, optional): DualEntry transaction ID to pair with in a one-to-one match. Pass this or--entry-id, not both.--entry-id(integer, optional): DualEntry entry ID for a partial match. Pass this or--transaction-id, not both.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Match one bank-feed row to one transaction
Confirm a many-to-many match from a file
Undo a match
--financial-transaction-id(integer, optional): Bank-feed row ID in the match group to undo. Pass this or--match-group-id.--match-group-id(integer, optional): Match group ID from a prior match response. Pass this or--financial-transaction-id.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Undo a match group
Generate a match file
bank-match match --file, or writes it to a file. On this subcommand, -o is short for --output.Flags:--output,-o(path, optional): File to write the template to, instead of standard output.--type,-t(string, default1:1): Template type:1:1,m:n, orpartial.
Write a many-to-many match template
Bank connections
Thebank-connections commands register bank connections, their accounts, and their transactions through the API, for organizations that send bank data to DualEntry themselves.List bank connections
--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--updated-after(datetime, optional): Return only connections updated at or after this time, as an ISO 8601 timestamp.--updated-before(datetime, optional): Return only connections updated at or before this time, as an ISO 8601 timestamp.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
CONNECTION_ID(integer, required): DualEntry bank connection ID.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List connections changed since September 1
Show one connection
Register a bank connection
--file,-f(path, required): JSON file with the connection to register.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Register a connection from a file
Unregister a bank connection
CONNECTION_ID(integer, required): DualEntry bank connection ID to unregister.
Unregister a connection
Register accounts on a connection
CONNECTION_ID(integer, required): DualEntry bank connection ID.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
CONNECTION_ID(integer, required): DualEntry bank connection ID.
--file,-f(path, required): JSON file with the array of accounts to create.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List a connection's accounts
Register accounts from a file
Push bank transactions
FINANCIAL_ACCOUNT_ID(integer, required): DualEntry financial account ID.
--file,-f(path, required): JSON file with the batch of transactions to push.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Push a batch of transactions
Generate a bank connection file
create, accounts create, or transactions push, or writes it to a file. On this subcommand, -o is short for --output.Flags:--output,-o(path, optional): File to write the template to, instead of standard output.--type,-t(string, defaultconnection): Template type:connection,accounts, ortransactions.
Write a transactions template
Data exports
Theexport-jobs commands request and track an on-demand refresh of a connected data warehouse destination, outside its regular schedule.Request a data export
--integration-id(integer, optional): Destination integration ID. You can omit it when your organization has exactly one connected destination.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Request an export
Wait for a data export to finish
0 when it completes, or 1 when it fails or the timeout passes, so it works as a step in a CI job.Arguments:JOB_ID(integer, required): Export job ID to poll until finished.
--interval(number, default5.0, minimum0.5): Seconds between status polls.--timeout(number, default1800.0, minimum1.0): Give up after this many seconds (default 30 minutes).--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
Request an export and wait for it
List and check data exports
--limit,-l(integer, default20): Maximum number of records to return.--offset(integer, default0): Number of records to skip before the first one returned.--all,-a(boolean, optional): Fetch every page of results instead of one.--status(string, optional, repeatable): Return only jobs with this status:pending,running,completed, orfailed. Repeat the flag to match more than one status.--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
JOB_ID(integer, required): Export job ID fromexport-jobs createorexport-jobs list.
--format,-o(string, defaulthuman): Output format:human(a table or detail view) orjson.
List running and pending exports
Check one export