Retrieving invoices in Zoho CRM is straightforward once your OAuth connection is established — you can fetch either a full list of invoices or a single invoice by its ID using two dedicated API operations.
Why this matters
If you're building an integration, automating billing workflows, or simply auditing your sales records programmatically, you'll need reliable access to invoice data stored in Zoho CRM. Knowing which endpoints to call — and how authentication is handled behind the scenes — saves significant debugging time. This guide is provided by Beam Help, your independent expert support for Zoho (not official Zoho support).
Step-by-step
Step 1. Ensure your Zoho CRM connection is active and your access token is valid. The system checks the stored token expiry and automatically refreshes it roughly two minutes before it expires, using the saved refresh_token from your connection record. If the refresh fails or no connection exists for your user, the API call cannot proceed. [2]
Step 2. Confirm that your OAuth scopes include the necessary Zoho CRM permissions. The ZohoCRM.org.ALL and related ZohoCRM scopes must be present in your authorised scope list for CRM data — including invoices — to be accessible. [8]
Step 3. To retrieve all invoices, issue a GET request to the /Invoices endpoint. In code, this is exposed as the get_invoices operation, which accepts an optional parameters dictionary (p) for filtering or pagination. A minimal call passes an empty dictionary if no filters are needed. [4]
# Retrieve all invoices (no filters)
result = api.get_invoices(p={})
# Retrieve invoices with optional query parameters
result = api.get_invoices(p={"page": 1, "per_page": 50})
Step 4. To retrieve a single invoice by its unique identifier, issue a GET request to /Invoices/{invid}, substituting the actual invoice ID. This is the getinvoice operation and requires only the inv_id string as its argument. [7]
# Retrieve one specific invoice
result = api.get_invoice(inv_id="4876000000123456")
Step 5. The underlying API client (getzohoapi) handles token refresh transparently via a tokenrefresher callback. If a mid-request token expiry occurs, the refresher fetches the latest refreshtoken from your database, calls ZohoOAuth.refreshtokens, and stores the new accesstoken and tokenexpiresat values before retrying. You do not need to manage this manually. [1]
Step 6. Parse the response from either call. Both getinvoices and getinvoice return the raw response from Zoho CRM's REST layer. For a list call, expect a paginated structure; for a single-record call, expect a record object keyed by the invoice fields. [4][7]
Common pitfalls
- Missing or expired connection: If
getzohoconnectionreturnsNone— meaning no row exists inzohoconnectionsfor the givenuserid— the API instance cannot be created and all invoice calls will fail silently. Always verify the connection record exists before making requests. [2]
- Token refresh returning no access token: During the refresh flow, if the response from
ZohoOAuth.refreshtokensdoes not contain anaccesstokenkey, the refresher returnsNoneand the request will be blocked. This typically indicates an expired or revokedrefresh_tokenrequiring the user to re-authenticate. [1][6]
- Insufficient OAuth scopes: If the scopes granted during OAuth authorisation do not include the required
ZohoCRMpermissions, Zoho's API will return a permission error rather than invoice data. Double-check that the correct CRM scopes were requested at connection time. [8]
- Wrong
apptypeparameter: Thegetzohoapihelper accepts anapptypeargument — passing"desk"instead of"crm"will route your request to Zoho Desk rather than Zoho CRM, where the/Invoicesendpoint does not exist. Always passapp_type="crm"when working with invoices. [1]
What to check
- Connection record exists: Confirm a valid row is present in your
zohoconnectionstable for the targetuserid, with a non-expiredrefresh_token. [2] - Scopes include CRM access: Verify that the OAuth authorisation included the necessary
ZohoCRMscope set, not just Zoho Desk scopes. [8] - Correct endpoint and ID format: For single-invoice retrieval, ensure the
inv_idvalue is the full Zoho CRM record ID (typically a long numeric string), not a display number or custom field value. [7]