Install
openclaw skills install quickbooksQuickBooks API integration with managed OAuth. Install only if you need QuickBooks accounting administration. Connect with a least-privileged QuickBooks account, verify the intended connection ID before each request, and revoke unused connections promptly. This integration can mutate accounting records — approve only specific write actions after checking the exact endpoint, account, resource ID, amounts, and consequence. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install quickbooksAccess the QuickBooks Online API with managed OAuth authentication. Manage customers, vendors, invoices, payments, and run financial reports.
# Query customers
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/quickbooks/v3/company/:realmId/query?query=SELECT%20*%20FROM%20Customer%20MAXRESULTS%20100')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/quickbooks/{endpoint-path}
The gateway proxies requests to quickbooks.api.intuit.com and the :realmId placeholder is automatically replaced with your company's realm ID from connection config. Only the endpoints documented in the API Reference section below are supported — always use specific endpoint paths from that section rather than constructing arbitrary paths.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your QuickBooks OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=quickbooks&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'quickbooks'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "quickbooks",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple QuickBooks connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/quickbooks/v3/company/:realmId/companyinfo/:realmId')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Always include the Maton-Connection header to ensure requests go to the intended QuickBooks company, especially before any write operation. If you have multiple connections and omit this header, the gateway uses a default connection, which may not be the intended account.
GET /quickbooks/v3/company/:realmId/companyinfo/:realmId
GET /quickbooks/v3/company/:realmId/query?query=SELECT%20*%20FROM%20Customer%20MAXRESULTS%20100
GET /quickbooks/v3/company/:realmId/customer/{customerId}
POST /quickbooks/v3/company/:realmId/customer
Content-Type: application/json
{
"DisplayName": "John Doe",
"PrimaryEmailAddr": {"Address": "john@example.com"},
"PrimaryPhone": {"FreeFormNumber": "555-1234"}
}
Requires Id and SyncToken from previous GET:
POST /quickbooks/v3/company/:realmId/customer
Content-Type: application/json
{
"Id": "123",
"SyncToken": "0",
"DisplayName": "John Doe Updated"
}
GET /quickbooks/v3/company/:realmId/query?query=SELECT%20*%20FROM%20Invoice%20MAXRESULTS%20100
POST /quickbooks/v3/company/:realmId/invoice
Content-Type: application/json
{
"CustomerRef": {"value": "123"},
"Line": [
{
"Amount": 100.00,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {"value": "1"},
"Qty": 1
}
}
]
}
POST /quickbooks/v3/company/:realmId/invoice?operation=delete
Content-Type: application/json
{
"Id": "123",
"SyncToken": "0"
}
POST /quickbooks/v3/company/:realmId/payment
Content-Type: application/json
{
"CustomerRef": {"value": "123"},
"TotalAmt": 100.00,
"Line": [
{
"Amount": 100.00,
"LinkedTxn": [{"TxnId": "456", "TxnType": "Invoice"}]
}
]
}
GET /quickbooks/v3/company/:realmId/reports/ProfitAndLoss?start_date=2024-01-01&end_date=2024-12-31
GET /quickbooks/v3/company/:realmId/reports/BalanceSheet?date=2024-12-31
POST /quickbooks/v3/company/:realmId/batch
Content-Type: application/json
{
"BatchItemRequest": [
{"bId": "1", "Query": "SELECT * FROM Customer MAXRESULTS 2"},
{"bId": "2", "Query": "SELECT * FROM Vendor MAXRESULTS 2"}
]
}
QuickBooks uses SQL-like queries:
SELECT * FROM Customer WHERE DisplayName LIKE 'John%' MAXRESULTS 100
Operators: =, LIKE, <, >, <=, >=, IN
All updates require the current SyncToken:
SyncTokenId and SyncToken in POST bodyconst response = await fetch(
'https://api.maton.ai/quickbooks/v3/company/:realmId/query?query=SELECT%20*%20FROM%20Customer',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
import os
import requests
response = requests.get(
'https://api.maton.ai/quickbooks/v3/company/:realmId/query',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'query': 'SELECT * FROM Customer MAXRESULTS 10'}
)
:realmId is automatically replaced by the routerMAXRESULTS to limit query resultsYYYY-MM-DD formatActive: falsecurl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| 400 | Missing QuickBooks connection |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited (10 req/sec per account) |
| 4xx/5xx | Passthrough error from QuickBooks API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
quickbooks. For example:https://api.maton.ai/quickbooks/v3/company/:realmId/queryhttps://api.maton.ai/v3/company/:realmId/query