Complete OAuth 2.0 authorization using Intuit's identity platform at https://appcenter.intuit.com; request the 'payments' scope (com.intuit.quickbooks.payment) — this is separate from the 'accounting' scope used by the QBO API.
Tokenize the card client-side using the Intuit.js library or the Payments JS SDK so that raw card numbers never touch your server; the SDK returns a single-use token.
POST to https://api.intuit.com/quickbooks/v4/payments/charges with a JSON body containing 'amount' (in dollars as a string, e.g., '10.55'), 'currency' ('USD'), and 'card' object containing the single-use token.
Include the header 'Request-Id' with a UUID you generate; this is the idempotency key — reusing the same Request-Id safely retries without double-charging.
For stored payment methods, first POST to /quickbooks/v4/customers/{customerId}/cards to vault the tokenized card, then reference the card ID in future charge requests.
Handle the response: a successful charge returns HTTP 201 with a 'status' of 'CAPTURED'; a declined card returns HTTP 402 with a 'code' field describing the decline reason.
Known gotchas
The QuickBooks Payments API and the QuickBooks Online (QBO) accounting API share the same OAuth infrastructure but are separate products with separate scopes and separate base URLs — using a QBO-only OAuth token against the Payments endpoint returns 401.
Amount must be sent as a string (not a numeric type) with exactly two decimal places; sending an integer or a value with more than two decimal places causes a 400 validation error.
Sandbox credentials are issued separately from production and must be explicitly requested from Intuit; testing in the wrong environment can result in subtle differences in card decline codes that don't reflect production behavior.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp