Repository navigation
feat: add pdf command to save transactions as QuickBooks-rendered PDFs - #15
robschaerer wants to merge 2 commits into
Conversation
`qbo pdf <entity> <id> [-o path]` fetches GET /{entity}/{id}/pdf with
Accept: application/pdf. The endpoint is reachable through `qbo get`,
but every request there sends Accept: application/json and QuickBooks
answers 500 "No match for accept header".
Supported for invoice, estimate, salesreceipt, creditmemo and
purchaseorder. The id must be numeric (it is interpolated into the
path), and a 200 whose body is not a PDF is refused rather than saved.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019jpxEQMLnxu4s6zSfHq8xR
Compared against a PDF downloaded from the QuickBooks web UI: the API rendering combines invoice lines that share a description into one summed line, where the UI lists them separately. The API returns the same bytes at every minorversion, so it is the renderer, not a request option. Say so instead of claiming it is the customer's document. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_019jpxEQMLnxu4s6zSfHq8xR
|
Thank you for this, and sorry for the wait. I read the whole diff. It looks well considered: it goes through the existing OAuth client and error mapping, validates the entity and numeric Id before building the URL, caps the response size, refuses a 200 that isn't a What's needed before it can be merged:
Nothing else is blocking from my side. Thanks again for the careful work and for documenting the behavior you saw. — OSS Maintainer (AI agent for @voska) |
What
Adds
qbo pdf <entity> <id> [-o path], which saves a transaction as the PDF the QuickBooks API renders for it.Note: the API rendering is not always identical to what the QuickBooks web UI prints or emails. On a real invoice, the API combined three lines that share a description into one summed line, while the PDF downloaded from the UI lists them separately. The same bytes come back at every
minorversion, so this is QuickBooks' renderer, not a request option. The docs say so.Why
The
/v3/company/{realm}/{entity}/{id}/pdfendpoint is already reachable throughqbo get invoice "123/pdf", but every request the client makes sendsAccept: application/json, and QuickBooks answers500 System Failure Error: No match for accept header. So there was no way to get a PDF out of the CLI.How
api.Client.PDFsendsAccept: application/pdfthrough the same OAuth client as every other call, so it uses the existing token refresh and error mapping (mapHTTPError).invoice,estimate,salesreceipt,creditmemo,purchaseorder. Others are rejected with exit 2.%PDFis refused rather than saved under a.pdfname.--dry-runprints the request and returns before any network call.downloadcommand: hint on stderr,{entity, id, path, bytes}on stdout.skills/qbo/SKILL.mdandreferences/COMMANDS.md.Testing
go test ./...passes. New tests cover the Accept header and path, rejection of a non-PDF 200 body, HTTP error mapping, entity support, input validation, and dry-run without network.qbo pdf invoice <id>returned a 45 KB single-page PDF with the correct header, customer, lines and total (lines with identical descriptions combined, as noted above).🤖 Generated with Claude Code
https://claude.ai/code/session_019jpxEQMLnxu4s6zSfHq8xR