qbo

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

qbo — QuickBooks Online CLI

qbo — QuickBooks Online CLI

Install

安装

bash
undefined
bash
undefined

macOS / Linux

macOS / Linux

brew install voska/tap/qbo
brew install voska/tap/qbo

Scoop (Windows)

Scoop (Windows)

scoop bucket add voska https://github.com/voska/scoop-bucket && scoop install qbo
scoop bucket add voska https://github.com/voska/scoop-bucket && scoop install qbo

Go (any platform)

Go (任意平台)

go install github.com/voska/qbo-cli/cmd/qbo@latest
go install github.com/voska/qbo-cli/cmd/qbo@latest
undefined
undefined

Getting Credentials

获取凭证

Requires an Intuit Developer account and a QuickBooks app for OAuth credentials.
  1. Sign up at https://developer.intuit.com and create an app from the dashboard.
  2. Select QuickBooks Online and Payments as the platform.
  3. Under Keys & credentials, find your Client ID and Client Secret.
  4. Add a Redirect URI (see below).
See Intuit's OAuth 2.0 guide for the full walkthrough.
需要Intuit开发者账户和QuickBooks应用以获取OAuth凭证。
  1. 访问https://developer.intuit.com注册账户,从控制台创建一个应用。
  2. 选择QuickBooks Online and Payments作为平台。
  3. Keys & credentials下找到你的Client IDClient Secret
  4. 添加一个Redirect URI(详见下文)。
完整流程请参考Intuit的OAuth 2.0指南

Redirect URI Options

重定向URI选项

Sandbox allows
http://localhost:8844/callback
— just register it in the Intuit portal and
qbo auth login
handles everything automatically.
Production does not allow localhost. Three options:
  1. Tunnel/funnel address — Route a domain (e.g.
    https://auth.yourdomain.com
    ) back to your machine. Register it as the redirect URI. Use
    --redirect-uri
    or set
    QBO_REDIRECT_URI
    .
  2. Login on the same machine — If the agent runs on a machine with a browser, use a tunnel so localhost callbacks work.
  3. Non-resolving domain — Register any domain you own (e.g.
    https://yourdomain.com
    ) as the redirect URI. After authorizing, the browser redirects there with
    ?code=...&realmId=...&state=...
    in the URL. Copy the full URL from the browser and paste it back into
    qbo auth login
    (or provide it to the agent to exchange manually).
沙箱环境允许使用
http://localhost:8844/callback
——只需在Intuit门户中注册该地址,
qbo auth login
会自动处理所有流程。
生产环境不允许使用localhost,有三种方案:
  1. 隧道/代理地址——将域名(例如
    https://auth.yourdomain.com
    )路由到你的本地机器。将其注册为重定向URI,使用
    --redirect-uri
    参数或设置环境变量
    QBO_REDIRECT_URI
  2. 本地机器登录——如果代理在带有浏览器的机器上运行,使用隧道工具使localhost回调生效。
  3. 非解析域名——注册你拥有的任意域名(例如
    https://yourdomain.com
    )作为重定向URI。授权完成后,浏览器会重定向到该地址,URL中包含
    ?code=...&realmId=...&state=...
    参数。复制浏览器中的完整URL并粘贴回
    qbo auth login
    (或提供给代理手动交换凭证)。

Setup

配置

bash
export QBO_CLIENT_ID=your_client_id
export QBO_CLIENT_SECRET=your_client_secret
bash
export QBO_CLIENT_ID=your_client_id
export QBO_CLIENT_SECRET=your_client_secret

Sandbox — uses localhost callback automatically

沙箱环境——自动使用localhost回调

qbo auth login --sandbox
qbo auth login --sandbox

Production — specify your redirect URI

生产环境——指定你的重定向URI

qbo auth login --redirect-uri https://yourdomain.com
qbo auth login --redirect-uri https://yourdomain.com

Or set it as env var / config so you don't need the flag every time

或者将其设置为环境变量/配置,这样就无需每次都添加该参数

export QBO_REDIRECT_URI=https://yourdomain.com qbo auth login
export QBO_REDIRECT_URI=https://yourdomain.com qbo auth login

Print the URL without opening a browser (useful for agents/remote)

只打印URL而不打开浏览器(适用于代理/远程场景)

qbo auth login --manual

For non-localhost redirect URIs, `qbo auth login` prints the auth URL and prompts you to paste the callback URL after authorizing.

Tokens are stored in the system keychain (macOS Keychain, Windows Credential Manager) with file-based fallback at `~/.config/qbo/tokens/`.
qbo auth login --manual

对于非localhost重定向URI,`qbo auth login`会打印授权URL,并提示你在授权后粘贴回调URL。

令牌会存储在系统密钥链中(macOS Keychain、Windows凭据管理器),如果系统密钥链不可用,会回退存储在`~/.config/qbo/tokens/`目录下的文件中。

Verify

验证

After auth, confirm everything works:
bash
qbo auth status
qbo company info --sandbox --json
If you get "no company ID", set one:
export QBO_COMPANY_ID=<realm_id>
or
qbo company switch <realm_id>
.
完成认证后,确认所有功能正常:
bash
qbo auth status
qbo company info --sandbox --json
如果提示"no company ID",请设置:
export QBO_COMPANY_ID=<realm_id>
qbo company switch <realm_id>

Troubleshooting

故障排除

ProblemFix
no company ID
export QBO_COMPANY_ID=<realm>
or
qbo company switch <realm>
ApplicationAuthorizationFailed
on production endpoint
Use
--sandbox
or re-authorize the app for a production company
OAuth state mismatchRestart
qbo auth login
and use the newly generated URL
Token expired
qbo auth refresh
or re-run
qbo auth login
问题解决方法
no company ID
export QBO_COMPANY_ID=<realm>
qbo company switch <realm>
生产环境端点出现
ApplicationAuthorizationFailed
使用
--sandbox
参数,或重新为生产环境公司授权该应用
OAuth状态不匹配重新运行
qbo auth login
并使用新生成的URL
令牌过期
qbo auth refresh
或重新运行
qbo auth login

Response Structure

响应结构

QBO wraps all responses. Know the shapes:
  • list
    /
    query
    returns
    {"QueryResponse": {"Invoice": [...], "startPosition": 1, ...}}
    . Use
    --results-only
    to unwrap to just the array.
  • get
    returns
    {"Invoice": {...}}
    . Use jq to drill in:
    qbo get invoice 123 --json | jq '.Invoice'
  • create
    /
    update
    returns the same wrapper as
    get
    .
  • report
    returns
    {"Header": {...}, "Rows": {...}}
    .
Always use
--json
when parsing output programmatically.
QBO会封装所有响应,了解其结构:
  • list
    /
    query
    返回
    {"QueryResponse": {"Invoice": [...], "startPosition": 1, ...}}
    。使用
    --results-only
    参数可直接获取数组内容。
  • get
    返回
    {"Invoice": {...}}
    。可使用jq工具提取内容:
    qbo get invoice 123 --json | jq '.Invoice'
  • create
    /
    update
    返回的结构与
    get
    相同。
  • report
    返回
    {"Header": {...}, "Rows": {...}}
程序化解析输出时,请始终使用
--json
参数。

Common Patterns

常用操作示例

bash
undefined
bash
undefined

List with filtering — --results-only gives you the array directly

带过滤的列表查询——--results-only参数直接返回数组

qbo list customers --sandbox --json --results-only qbo list invoices --where "Balance > '0'" --sandbox --json --results-only
qbo list customers --sandbox --json --results-only qbo list invoices --where "Balance > '0'" --sandbox --json --results-only

Get by ID — drill into entity key with jq

通过ID获取详情——使用jq工具提取实体字段

qbo get invoice 145 --sandbox --json | jq '.Invoice' qbo get customer 58 --sandbox --json | jq '.Customer | {Id, DisplayName, Balance}'
qbo get invoice 145 --sandbox --json | jq '.Invoice' qbo get customer 58 --sandbox --json | jq '.Customer | {Id, DisplayName, Balance}'

Create from stdin

从标准输入创建资源

echo '{"DisplayName":"Acme Corp"}' | qbo create customer -f - --sandbox --json
echo '{"DisplayName":"Acme Corp"}' | qbo create customer -f - --sandbox --json

Create from file

从文件创建资源

qbo create invoice -f invoice.json --sandbox --json
qbo create invoice -f invoice.json --sandbox --json

Record a payment against an invoice

为发票记录付款

echo '{"CustomerRef":{"value":"58"},"TotalAmt":500,"Line":[{"Amount":500,"LinkedTxn":[{"TxnId":"145","TxnType":"Invoice"}]}]}' | qbo create payment -f - --sandbox --json
echo '{"CustomerRef":{"value":"58"},"TotalAmt":500,"Line":[{"Amount":500,"LinkedTxn":[{"TxnId":"145","TxnType":"Invoice"}]}]}' | qbo create payment -f - --sandbox --json

Sparse update (partial)

增量更新(部分字段)

echo '{"Id":"58","SyncToken":"0","DisplayName":"New Name"}' | qbo update customer 58 --sparse -f - --sandbox --json
echo '{"Id":"58","SyncToken":"0","DisplayName":"New Name"}' | qbo update customer 58 --sparse -f - --sandbox --json

Reports

报表生成

qbo report profit-and-loss --start-date 2026-01-01 --end-date 2026-12-31 --sandbox --json qbo report balance-sheet --sandbox --json
qbo report profit-and-loss --start-date 2026-01-01 --end-date 2026-12-31 --sandbox --json qbo report balance-sheet --sandbox --json

Raw query

原生查询

qbo query "SELECT Id, DisplayName, Balance FROM Customer WHERE Active = true" --sandbox --json --results-only
undefined
qbo query "SELECT Id, DisplayName, Balance FROM Customer WHERE Active = true" --sandbox --json --results-only
undefined

Workflow: Create -> Invoice -> Payment

完整工作流:创建客户→创建发票→记录付款

bash
undefined
bash
undefined

1. Create customer

1. 创建客户

echo '{"DisplayName":"New Client","PrimaryEmailAddr":{"Address":"client@example.com"}}'
| qbo create customer -f - --sandbox --json | jq '.Customer.Id'
echo '{"DisplayName":"New Client","PrimaryEmailAddr":{"Address":"client@example.com"}}'
| qbo create customer -f - --sandbox --json | jq '.Customer.Id'

2. Create item (service)

2. 创建项目(服务类)

echo '{"Name":"Consulting","Type":"Service","IncomeAccountRef":{"value":"1"},"UnitPrice":150}'
| qbo create item -f - --sandbox --json | jq '.Item.Id'
echo '{"Name":"Consulting","Type":"Service","IncomeAccountRef":{"value":"1"},"UnitPrice":150}'
| qbo create item -f - --sandbox --json | jq '.Item.Id'

3. Create invoice (use IDs from above)

3. 创建发票(使用上述步骤获取的ID)

echo '{"CustomerRef":{"value":"CUSTOMER_ID"},"Line":[{"Amount":1500,"DetailType":"SalesItemLineDetail","SalesItemLineDetail":{"ItemRef":{"value":"ITEM_ID"},"Qty":10,"UnitPrice":150}}]}'
| qbo create invoice -f - --sandbox --json | jq '.Invoice | {Id, DocNumber, TotalAmt}'
echo '{"CustomerRef":{"value":"CUSTOMER_ID"},"Line":[{"Amount":1500,"DetailType":"SalesItemLineDetail","SalesItemLineDetail":{"ItemRef":{"value":"ITEM_ID"},"Qty":10,"UnitPrice":150}}]}'
| qbo create invoice -f - --sandbox --json | jq '.Invoice | {Id, DocNumber, TotalAmt}'

4. Record payment

4. 记录付款

echo '{"CustomerRef":{"value":"CUSTOMER_ID"},"TotalAmt":1500,"Line":[{"Amount":1500,"LinkedTxn":[{"TxnId":"INVOICE_ID","TxnType":"Invoice"}]}]}'
| qbo create payment -f - --sandbox --json
undefined
echo '{"CustomerRef":{"value":"CUSTOMER_ID"},"TotalAmt":1500,"Line":[{"Amount":1500,"LinkedTxn":[{"TxnId":"INVOICE_ID","TxnType":"Invoice"}]}]}'
| qbo create payment -f - --sandbox --json
undefined

Agent Introspection

代理自省

bash
qbo schema --json             # Full CLI tree, all entities, all flags
qbo schema get --json         # Schema for a specific command
qbo exit-codes --json         # Exit codes as JSON
bash
qbo schema --json             # 完整CLI树、所有实体、所有参数
qbo schema get --json         # 特定命令的 schema
qbo exit-codes --json         # 以JSON格式返回退出码

Exit Codes

退出码

0=success, 1=error, 2=usage, 3=empty, 4=auth required, 5=not found, 6=forbidden, 7=rate limited, 8=retryable, 10=config error.
0=成功, 1=错误, 2=使用方法错误, 3=空结果, 4=需要认证, 5=未找到资源, 6=权限不足, 7=请求受限, 8=可重试错误, 10=配置错误。

Reference

参考文档

See references/COMMANDS.md for full command reference.
完整命令参考请查看references/COMMANDS.md