Retrieving all contacts linked to a specific product in Zoho Desk is straightforward via the REST API — a single authenticated GET request to the products endpoint returns the full contact list.
Why this matters
When your support team needs to understand which customers are affected by a particular product issue, or when you want to build automated workflows around product-specific contact segments, you need a reliable way to pull that association data programmatically. This is especially useful for bulk notifications, reporting, or syncing Zoho Desk data with external systems. Note that Beam Help is independent expert support for Zoho — we are not official Zoho support.
Step-by-step
Step 1. Identify the product_id for the product whose contacts you want to retrieve. This is the unique identifier Zoho Desk assigns to each product record. You can find it by inspecting the product URL in the Desk UI or by querying your products list endpoint first. [1]
Step 2. Construct your GET request to the following endpoint, substituting your actual product identifier:
GET /api/v1/products/{product_id}/contacts
This operation is named listcontactsassociatedwithproduct in the Zoho Desk API. [1]
Step 3. Include your authentication headers (OAuth 2.0 bearer token) and, optionally, pass a p parameter dictionary to control pagination or filtering. The p argument maps to query parameters appended to the request URL. [1]
Step 4. Send the request. A minimal Python implementation looks like this:
def list_contacts_associated_with_product(self, product_id: str, p: dict = None):
return self.c.request("GET", f"/api/v1/products/{product_id}/contacts", p, None)
The fourth argument (None) indicates there is no request body for this GET call. [1]
Step 5. Parse the response. The API returns the contacts associated with that product. Iterate over the result set to access individual contact records, and use the p pagination parameter to page through large result sets if needed. [1]
---
Bonus: reverse lookup and association
If you need to go the other direction — finding all products linked to a specific contact — use the inverse endpoint:
GET /api/v1/contacts/{contact_id}/products
This operation (listproductsbycontact) accepts a contactid and an optional p parameter. [2]
You can also create new product-contact associations in either direction:
- To associate contacts with a product, send a POST to
/api/v1/products/{product_id}/contactswith adatapayload containing the contact identifiers. [4] - To associate products with a contact, send a POST to
/api/v1/contacts/{contact_id}/productswith the relevant product data. [3]
---
Common pitfalls
- Wrong ID type: Passing a contact ID where a product ID is expected (or vice versa) will return an empty result or a 404. Double-check which identifier you are using before making the call. [1]
- Missing pagination handling: If a product has a large number of associated contacts, the API will paginate results. Failing to pass the correct
pparameter on subsequent calls means you will only see the first page of contacts. [1] - No request body on GET: The
listcontactsassociatedwithproductcall passesNoneas the body argument. Sending a body on a GET request may cause unexpected behaviour — keep it empty. [1] - Confusing the accounts endpoint: There is a separate endpoint,
GET /api/v1/products/{product_id}/accounts, for listing *accounts* (not contacts) associated with a product. Make sure you are hitting the/contactspath and not/accountsif contacts are what you need. [7]
---
What to check
- Verify the product ID is correct by confirming the product exists in your Zoho Desk portal before making the API call.
- Confirm the response contains contacts and is not an empty array — if it is empty, check whether contacts have actually been associated with that product in the Desk UI or via the POST endpoint. [^1, ^4]
- Check pagination — if the expected number of contacts seems low, inspect whether additional pages exist by reviewing the pagination metadata in the response and adjusting your
pparameter accordingly. [1]