Use when creating Zoho Books invoices from contractor invoice PDFs and timesheet CSVs. Handles OAuth token refresh, idempotent invoice creation, marking as sent without emailing, and recording payment.
Automates creation of backdated Zoho Books invoices from A.Team bimonthly timesheet exports.
748222255)2647379000002736001)2647379000000074181)ATEAM-{statement_number} (e.g. ATEAM-79897).env file:
ZOHO_CLIENT_ID, ZOHO_CLIENT_SECRET, ZOHO_REFRESH_TOKEN, ZOHO_ORG_IDopenclaw-zoho-client-id etc., synced to ~/.openclaw/.envpdftotext (poppler-utils)Dylan drops exports in ~/Downloads/:
If timesheet CSV hours × $90 ≠ invoice PDF amount: use invoice PDF amount. The invoice = what was actually paid.
/invoices with backdated date and ignore_auto_number_generation=true/invoices/{id}/status/sent — marks sent WITHOUT emailing the customer/customerpayments — records payment against Bluevine accountAuthorization: Zoho-oauthtoken {access_token} (NOT Bearer)POST accounts.zoho.com/oauth/v2/token with grant_type=refresh_token&ignore_auto_number_generation=true to POST /invoicesPOST /invoices/{id}/status/sentPOST /customerpayments with account_id = Bluevine bank account IDZohoBooks.invoices.CREATE,READ,UPDATE + contacts.CREATE,READ + settings.READ + customerpayments.CREATE,READ,UPDATE + banking.READ
| Number | Period | Hours | Total | Status |
|---|---|---|---|---|
| ATEAM-79897 | Nov 1-15 2025 | 8h | $720 | paid |
| ATEAM-80962 | Nov 16-30 2025 | 76h | $6,840 | paid |
| ATEAM-81212 | Dec 1-15 2025 | 88h | $7,920 | paid |
| ATEAM-81706 | Dec 16-31 2025 | 70h | $6,300 | paid |
| ATEAM-82231 | Jan 1-15 2026 | 82h | $7,380 | paid |
Later periods (Jan 16+, Feb, Mar 2026) still to be processed.
# PDF only (CSV not required — skips discrepancy check)
zoho-ateam-invoice invoice.pdf
# PDF + CSV (enables hours/total cross-check, warns on mismatch)
zoho-ateam-invoice --csv timesheet.csv invoice.pdf
# Dry run — parse and show what would happen, no API calls
zoho-ateam-invoice invoice.pdf --dry-run
zoho-ateam-invoice --csv timesheet.csv invoice.pdf --dry-run
# List existing ATEAM-* invoices in Zoho Books
zoho-ateam-invoice --list
Recommended flow: always --dry-run first, then run for real.