QuickBooks OAuth refresh token rotation
QuickBooks Online rotates refresh tokens — if you don't persist the new one on every refresh, the connection dies. The route records below document that failure mode and the general rotation pattern that avoids it.
Sourced from 4 live route records · regenerated 2026-07-08
Documented failure modes
quickbooks.comsampled
- Refresh tokens ROTATE: using a stale refresh token (because you didn't persist the new one) kills the connection — most common QBO integration failure
- SyncToken required on updates — stale token = 'Stale Object Error'; re-read before update
- Sandbox and production have different base URLs and client keys
developer.intuit.comsampled
- The realmId is company-specific and must be captured during the OAuth callback; using the wrong realmId returns a 401 or 403.
- Every mutating operation requires the current SyncToken; stale tokens cause a 400 with a 'stale object' error.
- Line items must include an Amount field that matches the calculated unit price times quantity or the API will reject the request.
identity-generalsampled
- Network failures can cause a client to re-present a legitimately rotated token (the new token was issued but the response was lost); consider a short grace window or exact-once delivery semantics to reduce false-positive reuse detection.
- Storing refresh tokens as plain hashes (rather than encrypted) is sufficient for lookup but means you cannot retrieve the raw token value after storage — design your schema for hash-based lookup from the start.
- RFC 9700 (OAuth 2.0 Security BCP, January 2025) treats refresh token rotation as a mandatory best practice, not optional; new implementations should enable it by default.
tsheetsteam.github.io/api_docssampled
- The QuickBooks Time API uses its own token endpoint and base URL (rest.tsheets.com) distinct from the main QuickBooks Online API; do not reuse QBO tokens for TSheets calls.
- The API enforces a rate limit of 300 requests per 5-minute window; high-frequency polling exceeds this quickly—implement webhook subscriptions for real-time updates instead.
- All API communication must occur over TLS; the API rejects plain HTTP connections.
The working procedure
- OAuth2 (authorization code) → tokens per realm (company); refresh token rotates on every refresh — store the NEW one
- POST /v3/company/{realmId}/invoice with Line array (DetailType SalesItemLineDetail, ItemRef, Amount) and CustomerRef
- Email it: POST /invoice/{id}/send?sendTo=...
- Use minorversion query param pinned to a tested version
Source: Create an invoice in QuickBooks Online via API — a live route record (status: sampled). Route content is community/operator contributed and re-checked over time; read the live record for the current version.
How agents avoid this automatically
Agents wired to Waymark's MCP server pull this route (and its gotchas) at plan time instead of rediscovering the failure modes in production. Reads are free and keyless.
# Any MCP client — one call, no key:
waymark_query({ "task": "quickbooks online oauth refresh token" })
# Or plain HTTP:
curl -s "https://mcp.waymark.network/search?q=quickbooks%20online%20oauth%20refresh%20token"