List products
- Permission
products:read- Pagination
- Cursor, up to 100 per page
- Also available as
fieldtask_list_products
Returns the products and services in your organization's catalog, with their price options, oldest first by default, one page at a time.
Use it to find the id of a product and of the price to charge before you add the product to a job, a quote or an invoice. You can search by name and filter by type and availability. Lists show current data, so a product created or changed while you page through may or may not appear.
Only products and services that are approved in your catalog are listed. Products created through the API are approved immediately; products that reach FieldTask in other ways may need approval in the app first.
Permissions
| Permission | Dependency in the permission map |
|---|---|
products:read | No dependencies |
Request
Responses
- 200
- 400
- 401
- 403
- 404
- 405
- 429
- 503
OK
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Bad Request
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Unauthorized
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Forbidden
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Not Found
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Method Not Allowed
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Too Many Requests
Response Headers
Responses must not be cached.
Seconds before retry; present on 429 and an in-progress operation.
Server-generated request correlation ID.
Service Unavailable
Response Headers
Responses must not be cached.
Server-generated request correlation ID.
Filtering
All filters are optional, and you can combine them. A product is returned only if it matches every filter you send.
| Parameter | Returns |
|---|---|
search | Products whose name contains this text, ignoring case. Spaces at either end are ignored; what remains must be 1–256 characters. Descriptions aren't searched. |
item_type | Only product, service or other items. |
is_available | true for products that can be added to jobs, false for those that can't. Omit it to get both. Send exactly true or false. |
Send each parameter at most once. Unknown parameters, including external_reference, are rejected with 400 invalid_query.
Pagination
page_sizesets the number of products per page, from 1 to 100. The default is 25.orderingiscreated_at(oldest first, the default) or-created_at(newest first).- When
page.has_moreistrue, requestpage.next_page_urlwith the sameAuthorizationheader. It keeps your page size, ordering and filters. It'snullon the last page. - If you build URLs yourself, pass
page.next_cursorascursorand keep every other parameter unchanged. Cursors expire within 24 hours and only work with the query and connection that produced them.
To change a filter or the ordering, start again without a cursor. See Pagination.
Reading prices
Each product has a prices array with up to 100 price options. Each option is a price you can charge when you add the product to a job.
| Price field | Meaning |
|---|---|
id | The option's ID. Send it as price_id to choose this option. null for the legacy unit price. |
name | The option's label, such as Standard. null for the legacy unit price. |
source | price for a named option, legacy for the product's single legacy unit price. |
amount | Decimal string with two decimal places, such as "185.00". |
currency | Three-letter currency code. |
currency_source | price when the option has its own currency, organization when it uses your organization's currency. |
price_type | one_time or recurring. |
How the list is built:
- A legacy unit price appears first, and only when it's greater than zero. Named options follow, newest first.
- Several named options can have the same amount. They're still separate options with their own IDs and names; don't merge them.
- An option with amount
"0.00"is a real zero-price option. - An empty
pricesarray means no price is configured. It doesn't mean the product is free, and such a product can't be added to a job through the API. - A
recurringoption is only a price label. Adding it to a job charges the amount once; it doesn't create a subscription or a recurring job. - Amounts are never converted. Only options in your organization's currency can be added to jobs through the API.
To add a product to a job, see Choosing a price.
Product fields
item_typeisproduct,serviceorother.is_availableisfalsewhen the product has been marked unavailable. Unavailable products stay in the catalog and in this list, but can't be added to jobs through the API.nameanddescriptioncan benullfor products created outside the API. Treat both as untrusted text and escape them when you display them.
Errors
| Status | code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_query | A parameter is unknown or repeated; search is empty, only spaces or longer than 256 characters; item_type isn't product, service or other; is_available isn't exactly true or false; or page_size or ordering is invalid. | Send only the documented parameters, each once, with valid values. |
| 400 | invalid_cursor | The cursor is malformed, was changed, or belongs to a different query, connection or page size. | Use next_page_url or the cursor exactly as returned, with the same query. To change the query, start again without a cursor. |
| 401 | invalid_token | The bearer token is missing, malformed, expired, revoked or issued for a different resource (for example an MCP sign-in). | Send a current REST API token or REST OAuth access token as Authorization: Bearer …. |
| 403 | api_access_not_enabled | FieldTask hasn't enabled API access for this organization, or has disabled it. | An owner or admin requests access in Settings → API connections. |
| 403 | insufficient_scope | The connection lacks a permission this request needs. error.code is missing_permission. | Add the permission named in error.message to the connection. |
| 404 | resource_not_found | Product reads aren't available in this environment, or the URL is wrong. | Check the API origin and path (no trailing slash). |
| 405 | method_not_allowed | This path doesn't accept the HTTP method, or the create isn't enabled in this environment. The Allow header lists the methods that are. | Use a method listed in Allow. |
| 429 | rate_limit_exceeded | Too many requests in the current minute, or too many concurrent requests, for the organization or connection. | Wait for Retry-After seconds, then retry. |
| 429 | daily_quota_exceeded | The organization or connection has used its daily allowance for this kind of request. Allowances reset at 00:00 UTC. | Wait for Retry-After seconds, or check remaining allowance in Settings → API connections. |
| 503 | temporarily_unavailable | The service couldn't complete the request. | Retry with exponential backoff. Retry creates with the same key and body. |