Zoho Projects API Documentation
Text copied
File not found
Introduction

Zoho Projects provides a comprehensive set of REST APIs to manage your projects, connect third party applications, and transfer or retrieve data from Zoho Projects.

API Root Endpoint

https://projects.zoho.com
Getting Started
Mandatory Headers

Zoho Projects APIs require a mandatory header.

  1. Authorization : The OAuth access token to authenticate the user accessing data.

Example

$ curl -X GET https://projects.zoho.com/api/v3/portal/{portal_id}/tasks
-H "Authorization: Bearer 1000.03xxxxxxxxxxxxxxxxxa5317.dxxxxxxxxxxxxxxxxxfa"
What's New in V3

Version-3 (V3) builds on the existing Zoho Projects API by introducing a more consistent structure across endpoints and extending support for common integration needs. Updates to areas like date formats, filtering, custom fields, and pagination make it easier to work with data in a predictable way. In this section, you'll find what's new in v3, what has been updated, and what to review when moving from v2.

V3 API - Quick Example

GET /api/v3/portal/{portal_id}/projects
Authorization: Bearer {token}

Response

{
  "page_info": {
    "page": 1,
    "per_page": 100,
    "page_count": 100,
    "has_next_page": true
  },
  "projects": [...]
}
Enhancements in v3 API

V3 introduces a more consistent and structured way to work with the Zoho Projects API. It simplifies how data is formatted, how requests are constructed, and how responses are handled, making integrations easier to build and maintain. These updates also bring more clarity when working with filters, custom fields, and large datasets.

V3 Improvements at a Glance

// 1. Dates → ISO 8601
"due_date": "2024-05-26T00:00:00.000Z"

// 2. Filtering → one request
"filter": {
  "criteria": [
    {
      "field_name": "status",
      "criteria_condition": "all_open"
    }
  ],
  "pattern": "1"
}

// 3. Custom fields → api_name
"cf_priority_level": "High"

// 4. Request = Response
"assignee": { "zpuid": "...", "name": "John Doe" }

// 5. Pagination → page-based
"page_info": {
  "page": 1,
  "per_page": 100,
  "page_count": 100,
  "has_next_page": true
}
Consistent Date and Time Format

All date and time values follow a single ISO 8601 format across endpoints. This ensures consistent parsing and removes the need to handle multiple formats.

Type V2 V3
Date only "05-26-2014" (MM-DD-YYYY) "2024-05-26" (YYYY-MM-DD)
Datetime "05-13-2014 05:57 PM" (12-hour) "2024-05-26T11:25:58.000Z" (ISO 8601)
Human-readable "May 26, 2014" removed
Epoch 1399620397255 removed
Date input format MM-DD-YYYY YYYY-MM-DD

The *_long epoch fields are removed. ISO 8601 timestamps are universally parseable.

Advanced Filtering

You can define multiple conditions within a single request using a structured filter object. Filtering is processed entirely on the server, so only relevant records are returned.

  • Supported conditions:
    • is
    • is_not
    • contains
    • starts_with
    • before
    • after
    • is_empty
    • is_not_empty
    • between
  • Pattern logic: Combine conditions using AND, OR, and grouping - e.g. "(1 OR 2) AND 3"
  • Custom field support: Use the api_name of any custom field as the criteria field_name

For the complete syntax reference, see the Filter Guide.

Advanced Filter - Overdue & Assigned

{
  "filter": {
    "criteria": [
    {
      "field_name": "due_date",
      "criteria_condition": "today"
    },
    {
      "field_name": "assignee",
      "criteria_condition": "is",
      "value": ["user_zpuid"]
    }
  ],
  "pattern": "1 AND 2"
  }
}
Standardized Custom Fields

Custom fields now use clear and consistent api_name values. This makes it easier to reference them across requests, filters, and responses without additional mapping.

V2 V3
In requests UDF_CHAR1, UDF_LONG2 expected_date, priority_level
In responses Same UDF_ keys, no context Same api_name, consistent everywhere
  • Stable references - field identifiers don't shift when other fields are added or removed
  • Works everywhere - same api_name in requests, responses, and filter criteria

For full details, see Custom Fields.

V3 Custom Field in Response

{
  "expected_date": "2024-05-26"
}

V3 Custom Field in Filter

{
  "criteria": [
    {
      "field_name": "expected_date",
      "criteria_condition": "is",
      "value": ["2024-05-26"]
    }
  ]
}
Request and Response Structure

The same field structure is used in both requests and responses. This improves predictability and reduces the need for transformation logic when handling API data.

Aspect V2 /restapi V3 /api/v3
Content Type application/x-www-form-urlencoded application/json
Body Style Flat, form-encoded parameters JSON body, nested objects
Dates Mixed formats (MM-DD-YYYY, epoch, text) ISO 8601 everywhere
Related Data Flat fields (person_responsible, assignee_name) Grouped objects (assignee, status)
List Responses No pagination metadata page_info block with has_next_page

V3 Request (JSON)

POST /api/v3/portal/{portal_id}/projects/{project_id}/tasks
Content-Type: application/json

{
  "name": "Task Name",
  "assignee": { "zpuid": "user_id" },
  "due_date": "2024-05-26",
  "priority": "High"
}

V3 Response

{
  "page_info": {
    "page": 1,
    "per_page": 100,
    "page_count": 100,
    "has_next_page": true
  },
  "tasks": [
    {
      "id": "12345",
      "name": "Task Name",
      "due_date": "2024-05-26T00:00:00.000Z",
      "assignee": {
        "zpuid": "...",
        "name": "John Doe",
        "email": "..."
      },
      "status": {
        "id": "...",
        "name": "Open",
        "color": "#...",
        "is_closed_type": false
      }
    }
  ]
}
Pagination

Pagination is now page-based, making it easier to work with large datasets.

  • Use page and per_page to control results
  • has_next_page indicates if more records are available
  • Avoids duplicate or skipped records
  • No need for manual offset calculations

For full details and examples, see Pagination.

Base URL Structure

All endpoints in v3 follow a consistent URL pattern. The base URL is simplified and standardized, and trailing slashes are no longer required. This makes it easier to construct and predict endpoint URLs across the API.

V2 V3
Base URL /restapi/portal/{portal_id}/projects/ /api/v3/portal/{portal_id}/projects
Trailing slashes Some endpoints require trailing / No trailing slashes
Operation V2 V3
List tasks GET /restapi/portal/{portal_id}/projects/{project_id}/tasks/ GET /api/v3/portal/{portal_id}/projects/{project_id}/tasks
Note
  • If you're migrating from V2, update all endpoint URLs - the /restapi/ prefix is replaced with /api/v3/.
Quick Comparison
Area V2 (/restapi) V3 (/api/v3)
URL Pattern /restapi/portals/ /api/v3/portals
Date Format "05-26-2014" or "May 26, 2014" or 1399620397255 "2024-05-26" (date only) or "2024-05-26T11:25:58.000Z" (ISO 8601)
Pagination index + range (offset-based) page + per_page with has_next_page
HTTP Method for Updates POST PATCH
Custom Fields UDF_ prefix (e.g. UDF_CHAR1) api_name (e.g. "expected_date")
Request / Response Schema Fields sent in requests often differed from response field names Request and response use the same field structure throughout
API Coverage Limited modules and endpoints Additional modules and endpoints, significantly expanding the overall API surface area

V3 Update Task Example

PATCH /api/v3/portal/{portal_id}/projects/{project_id}/tasks/{task_id}
Content-Type: application/json

{
  "assignee": {
    "zpuid": "user_id"
  },
  "due_date": "2024-05-26",
  "cf_priority_level": "High"
}
HTTP Methods

Zoho Projects currently supports the following methods.

Method
Purpose
GET
Retrieve data
POST
Add or create data and perform actions
PUT
Update data
PATCH
Partial updates
DELETE
Delete data
Error Codes

Zoho Projects uses HTTP status codes to indicate success or failure of API calls. Status codes 2xx indicate success, 4xx indicate error in the information provided, and 5xx indicate server side errors. The following table lists some commonly used HTTP status codes.

HTTP Status Codes
Status CodeDescription
200OK
201Created
202Accepted
204No content
206Partial Data
207Multi-status
400Bad request
401Unauthorized
402Payment Required
403Forbidden (Unauthorised access)
405Method not allowed (Method called is not supported for the API invoked)
409Conflict
429Too Many Requests
500Internal error
501Not Supported
Other Error Responses

Besides HTTP status codes and their corresponding error messages, error responses for Zoho Projects APIs also include a machine-parsable errorCode param to simplify error handling.

The different errorCodes and their uses are described below

URL_RULE_NOT_CONFIGURED 400

Please check if the URL you are trying to access is correct.

Resolution: The request URL specified is incorrect. Specify a valid request URL.

URL_RULE_NOT_CONFIGURED

INVALID_OAUTHTOKEN 400

This errorCode appears if the OAuthToken is invalid or has expired.

Resolution: Regenerate OAuthToken and try again.

INVALID_OAUTHTOKEN

INVALID_INPUTSTREAM 400

The HTTP request specified has an invalid input parameter.

Resolution: The request URL input parameter specified is incorrect. Specify a valid request input parameter URL.

INVALID_INPUTSTREAM

INVALID_METHOD 400

The http request method type is not a valid one

Resolution: You have specified an invalid HTTP method to access the API URL. Specify a valid request method.

INVALID_METHOD

INVALID_PARAMETER_VALUE 400

The HTTP request specified has an invalid parameter value.

Resolution: The request URL input parameter value specified is incorrect. Specify a valid request input parameter value.

INVALID_PARAMETER_VALUE

INTERNAL_SERVER_ERROR 500

Server encountered an unexpected error. Contact

Resolution: support@zohoprojects.com

INTERNAL_SERVER_ERROR

API Limits

Zoho Projects APIs are governed by rate limits to ensure fair usage and optimal performance of all users.

Notes
  • Each API can be invoked up to 200 times within a 2-minute window.
  • The limit is applied per API endpoint.
Rate Limit Info

Each API response includes the following headers to help you monitor your usage:

  • RateLimit: Total allowed requests in the current window (e.g., 200).
  • RateLimit-Remaining: Remaining requests available in the current window.
  • RateLimit-Window: Duration of the rate limit window (e.g., 120 seconds).
  • RateLimit-Window-Unit: Time unit for the rate limit window (e.g., seconds).
  • Retry-After: Time (in seconds) to wait before retrying the request after the rate limit has been exceeded.
Note

Retry-After key is returned only when the rate limit has been exceeded.

Rate Limit Exceeded

If the number of requests exceeds the allowed limit:

  • The specific API will be temporarily blocked for 10 minutes.
  • During this period, all further requests to that API will fail.
  • A Retry-After header will be included in the response, indicating the remaining time (in seconds) before the API becomes available again.
Important Notes
  • The restriction applies only to the API that exceeds the limit, not all APIs.
  • After the 10-minute cooldown, the API will become available automatically.
  • Continuous violations may impact application performance and reliability.
Best Practices

To avoid hitting rate limits:

  • Implement retry mechanisms using the Retry-After header.
  • Use exponential backoff instead of immediate retries.
  • Avoid sending unnecessary or duplicate requests.
  • Use batch APIs (if available) to reduce the number of calls.
  • Cache frequently used data whenever possible.

Request

GET /api/v3/portal/{portal_id}/projects

Rate Limit Info

RateLimit = 200
RateLimit-Remaining = 199
RateLimit-Window = 120
RateLimit-Window-Unit = seconds
Retry-After = 540 (seconds remaining)

v3 uses page-based pagination on all list endpoints. Pass page and per_page as query parameters to control which page of results is returned.

Query Parameters
Parameter Type Description
page Integer Page number (starting from 1). Defaults to 1 if omitted.
per_page Integer Number of records per page. Defaults to 100 if omitted. Supported values: 1-200.
Response

Every list response includes a page_info block. The has_next_page flag tells your client precisely when to stop fetching — no offset calculations, no risk of duplicate or skipped records.

Field Type Description
page Integer Current page number
per_page Integer Records per page
page_count Integer Total number of records in the result set
has_next_page Boolean true if more pages exist, false if this is the last page

Request

GET /api/v3/portal/{portal_id}/projects/{project_id}/tasks?page=2&per_page=50

page_info Response

{
  "page_info": {
    "page": 2,
    "per_page": 50,
    "page_count": 10,
    "has_next_page": true
  }
}
API Names

Understand, locate, and use API names for modules, fields, and related apis in Zoho Projects.

An API name is a unique identifier assigned to every module and field in Zoho Projects.

While display names (labels shown in the UI) can be renamed and may include spaces or special characters, API names provide a consistent reference that remains unchanged across API requests and responses.

Display Name vs. API Name
Aspect Display Name API Name
Purpose Label shown in the UI Identifier used in APIs
Example Start Date start_date
Stability Can be changed Remains constant
Used In Forms, views, layouts Requests, responses, filters
The field settings screen, with the API Name of each field shown beside its display name.
Usage

API names are used in all programmatic interactions with Zoho Projects.

Requests and Responses

API names appear as keys in request payloads and response data. Fields such as priority, status, and department are referenced using their API names rather than display labels.

This applies to operations such as creating, updating, retrieving, and filtering records.

Retrieve API Names

API names for modules and fields in Zoho Projects can be accessed through the product or using APIs.

Method 1:

API names for custom fields are available directly within the Fields section in Zoho Projects, alongside other field details.

  • Navigate to Setup > Customization > Fields.
  • Select the required module.
  • Use the Search Fields option to locate a specific field from the Fields list.
  • Copy the API name to use it in the API operations.
Method 2:

The Modules API returns metadata for all modules in a portal, including their API names. The Fields API returns metadata for all fields in a module, including API names, data types, and whether a field is custom. Together, they provide a complete reference of available modules and fields for API usage.

  • Refer to Get Modules for the list of modules and their API names.
  • Refer to Get Fields Info for field-level details including API names.
Custom Fields

Send custom field values when creating or updating records through Zoho Projects APIs.

Custom fields are configured within module layouts to capture additional information based on business needs. Use the corresponding field API names to pass values in the request payload.

For example, a checkbox custom field can be used to track a project condition, and its value can be submitted as true or false in the API request.

Note
  • Custom field API names are currently supported only in the Tasks and Projects APIs.
  • Use the Custom Fields metadata API to retrieve field details such as API names and field types before passing values.
Field Types
Overview

Zoho Projects supports various custom field types, such as text, numeric, URL, date, and time. Below are the field types available in the Create and Update APIs.

Note
  • Send all inputs as an input stream (application/json).
  • Use API names for custom fields.
Single-Line Field

Captures text in a single line. Maximum length: 200 characters

JSON Schema

{ "key": "string"}

Example

{"title": "Project Ara"}
Multi-Line Field

Captures text in multiple lines. Use "\n" to separate lines. Maximum length: 1,000 characters

JSON Schema

{ "key": "string"}

Example

{"description": "The respective team\n is a prototype."}
Pick List Field

Allows selection of a single option from a predefined list. Maximum options: 50

JSON Schema

{ "key": "string"}

Example

{"Material": "Vinyl"}
Multi-Select Field

Allows selection of multiple options from a predefined list. You can add or remove values dynamically, or replace the existing values. Maximum selectable options: 100

Note
  • The add and remove options optimize the update process for Multi-Select fields, eliminating the additional GET call to retrieve existing values before updating.
  • You can directly add or remove values in an Update API request or use the Create API format.

Sample Input of Multi-Select Field in Create APIs

{ "key": [ "C", "D" ] }

Example

{ "parts_required": [ "HDD", "CD" ] }

Sample Input of Multi-Select Field in Update APIs

{ "key": [{ "add": [ "A", "B" ], "remove": [ "E", "F" ]}] }

Example

{ "parts_required": [{ "add": ["processor", "GPU"], "remove": ["POWER-CORD", "RAM"] }] }
User Pick List Field

Allows selection of a single user.

JSON Schema

{ "key": { "zpuid": "user id" }}

Example

{ "reporter": { "zpuid": "123454321" }}
Multi-User Field

Allows selection of multiple users from a predefined list. You can add or remove values dynamically, or replace the existing values. Maximum selectable users: 500

Note
  • The add and remove options optimize the update process for Multi-User fields, eliminating the additional GET call to retrieve existing values before updating.
  • You can directly add or remove values in an Update API request or use the Create API format.

Sample Input of Multi-User Field in Create APIs

{ "key": [ { "zpuid": "User Id 5" }, { "zpuid": "User Id 6" } ] }

Example

{ "user_group": [ { "zpuid": "7845996622" },{ "zpuid": "7876456433" } ] }

Sample Input of Multi-User Field in Update APIs

{ "key": [ { "add": [{ "zpuid": "User Id 2" },{ "zpuid": "User Id 3" }],"remove": [ { "zpuid": "User Id 4" }, { "zpuid": "User Id 5" } ] }] }

Example

{ "user_group": [ { "add": [{ "zpuid": "712554144112" },{ "zpuid": "71255413512" }],"remove": [ { "zpuid": "778946456" }, { "zpuid": "71346753132" } ] }] }
Date Field

Captures date in the yyyy-MM-dd format (ISO 8601).

JSON Schema

{ "key": "string"}

Example

{"due_date": "2022-10-17","start_date":"2019-09-17","end_date": "2024-12-17"}
Time Field

Captures the time in HH:MM format.

JSON Schema

{ "key": "string"}

Example

{"start_time": "23:30","end_time": "13:30"}
Time Stamp Field

Captures date and time in ISO 8601 format. Use yyyy-MM-dd'T'HH:mm:ss'Z' for UTC or yyyy-MM-dd'T'HH:mm:ss[+|-]HH:mm for other time zones. (ISO 8601 Time Stamp format).

JSON Schema

{ "key": "string"}

Example

{"start_time": "2022-12-16T18:56:00.000Z"}
Check Box Field

Captures boolean values (true or false) for a condition.

JSON Schema

{ "key": "boolean"}

Example

{"patent_applied": true}
Currency Field

Captures currency values with currency code, formatted amount, currency ID, and raw amount. Maximum length: 100 characters

JSON Schema

{ "currency": { "currency_code": "string", "formatted_amount": "string", "amount": "number (required)" }}

Example

{ "cost_per_item": { "currency_code": "USD", "formatted_amount": "$ 5,353.54", "amount": 325.50 }}
Percentage Field

Captures percentage values as numbers. Maximum length: 20 characters

JSON Schema

{ "key": "number"}

Example

{"completion_percentage": 10}
Number Field

Captures whole numbers. Maximum length: 19 digits

JSON Schema

{ "key": "number"}

Example

{"tests_passed": 35 }
Decimal Field

Captures decimal values. Maximum length: 17 digits

JSON Schema

{ "key": "number"}

Example

{"accuracy": 21.05}
Email Field

Captures email addresses. Maximum length: 200 characters

JSON Schema

{ "key": "string"}

Example

{"email":"chris@zylker.com"}
Phone Number Field

Captures phone numbers (Maximum length: 15 characters, including + and ()).

JSON Schema

{ "key": "string"}

Example

{"mobile":"1234567890"}
URL Field

Captures web links. If no protocol is specified, https:// is used by default. Maximum length: 200 characters

JSON Schema

{ "key": "string"}

Example

{"link":"https://projects.zoho.com"}
Filter Guide

The filter query parameter in Zoho Projects v3 enables retrieving only records that match defined conditions. This approach avoids fetching all records and applying filtering on the client side. This guide explains how to construct filter payloads, available conditions, and supported value formats.

Note
  • Pass the filter parameter as a URL-encoded JSON string
  • Combine one or more conditions using a pattern expression
  • Status and date presets are currently supported on specific modules only; support for the other modules will be provided soon.

Filter Example

{
  "criteria": [
    {
      "field_name": "name",
      "criteria_condition": "contains",
      "value": ["review"]
    }
  ],
  "pattern": "1"
}

URL-Encoded Filter in GET Request

GET /api/v3/portal/{portal_id}/projects/{project_id}/tasks?filter=%7B%22criteria%22%3A%5B%7B%22field_name%22%3A%22name%22%2C%22criteria_condition%22%3A%22contains%22%2C%22value%22%3A%5B%22review%22%5D%7D%5D%2C%22pattern%22%3A%221%22%7D
Filter Payload Structure

The filter payload is organized into key components that together represent how the conditions are defined and applied within a request : criteria and pattern.

Payload Properties
Property Data Type Description
criteria Array required Each property within the filter payload represents a specific part of a condition, contributing to how fields, operators, and values are interpreted during filtering.
field_name String required API name of the field to filter (e.g. status, due_date, name). Use the Get Field Info API to retrieve valid field names for a module.
criteria_condition String required Filter operation. Available conditions depend on the field type. See Conditions Reference.
value Array<String> optional Required for most conditions. Always an array. Omit for presets (today, is_empty). between requires exactly 2 values.
pattern String required Defines how criteria are combined using AND / OR logic. References criteria by their 1-based index in the array order (e.g. first criterion = 1, second = 2). Example: "(1 AND 2) OR 3".
Pattern Syntax

The pattern shows how criteria are combined and evaluated together. Each condition is referenced by its position in the list (starting from 1), and operators like AND, OR are used to define the relationship between them. Parentheses () can be used to group conditions and control how they are applied. The pattern is always required, with "1" used when only a single condition is present.

Pattern Meaning
"1" Single criterion
"1 AND 2" Both must match
"1 OR 2" Either can match
"1 AND 2 AND 3" All three must match
"(1 AND 2) OR 3" 1 & 2 together, or 3 alone
Value Format Rules

The value field represents the input used to evaluate a condition and is always structured as an array of strings. It is required for most conditions, while presets do not include a value. Range-based conditions such as between using exactly two values, and the format varies based on the field type.

Data Type Format Example Notes
Text String ["review"] Single value for most conditions
Date (specific) YYYY-MM-DD ["2024-11-04"] Single date value
Date (range) YYYY-MM-DD ["2024-11-01", "2024-11-30"] Exactly 2 values for between / not_between
User ZPUID ["4000000006061"] Single value for most conditions
Pick List Option name ["High"] Use the display name, not the ID
Multi Pick List Option ID ["4000000046001"] Use the option ID, not the display name
Check Box "true" / "false" or "1" / "0" ["true"] Both formats accepted
Numeric Numeric string ["100"] Numbers passed as strings
Note
  • Only is and is_not support multiple values (e.g. ["high", "medium"]).
  • is with multiple values = OR logic (matches any).
  • is_not with multiple values = AND logic (excludes all).
  • All other conditions accept a single value (or exactly 2 for between / not_between).
  • Preset conditions (today, is_empty, etc.) do not require a value array.

AND Pattern

{
  "criteria": [
    {
      "field_name": "assignee",
      "criteria_condition": "is",
      "value": ["4000000006061"]
    },
    {
      "field_name": "due_date",
      "criteria_condition": "is",
      "value": ["2026-12-31"]
    }
  ],
  "pattern": "1 AND 2"
}

OR Pattern

{
  "criteria": [
    {
      "field_name": "priority",
      "criteria_condition": "is",
      "value": ["high"]
    },
    {
      "field_name": "milestone",
      "criteria_condition": "is_empty"
    }
  ],
  "pattern": "1 OR 2"
}

Nested Pattern

{
  "criteria": [
    {
      "field_name": "priority",
      "criteria_condition": "is",
      "value": ["high"]
    },
    {
      "field_name": "due_date",
      "criteria_condition": "is",
      "value": ["2026-12-31"]
    },
    {
      "field_name": "assignee",
      "criteria_condition": "is",
      "value": ["4000000006061"]
    }
  ],
  "pattern": "(1 AND 2) OR 3"
}
Conditions Reference
Text Conditions

Used for text-based fields such as name, email, and custom fields, where matching is based on keywords or exact values. All comparisons are case-insensitive.

Condition API Value What it does Value
Contains contains Matches if the field has the substring anywhere ["review"]
Doesn't contain not_contains Excludes records containing the substring ["test"]
Starts with starts_with Matches the beginning of the field value ["API"]
Ends with ends_with Matches the end of the field value ["v2"]
Is is Exact match. Multiple values = OR logic ["High"] or ["High", "Medium"]
Is not is_not Excludes exact matches. Multiple values = AND logic ["Low", "None"]
Note
  • contains, not_contains, starts_with, and ends_with accept only a single value. Only is and is_not support multiple values in the array.
Comparison Conditions

Used for numeric and date fields, where values are evaluated based on comparisons like greater than, less than, or within a range.

Condition API Value What it does Value
Is is Exact match. Multiple values = OR logic ["100"] or ["100", "200"]
Is not is_not Excludes exact matches. Multiple values = AND logic ["0"]
Less than less_than Field value is less than the given value ["50"]
Less than or equal less_than_or_equal Field value is less than or equal ["50"]
Greater than greater_than Field value is greater than the given value ["50"]
Greater than or equal greater_than_or_equal Field value is greater than or equal ["50"]
Between between Field value within range (inclusive) ["10", "100"]
Not between not_between Field value outside range ["10", "100"]
Note
  • For date fields, use YYYY-MM-DD format. Single value: ["2024-11-01"]. Range: ["2024-11-01", "2024-11-30"].
Date Presets (Phases and Issues Modules only)

Includes ready-to-use conditions based on dates, evaluated relative to the current date without requiring manual input.

Relative to today:
Condition What it matches
today Current date
yesterday Previous day
tomorrow Next day
till_yesterday All dates up to yesterday
overdue Past due date
today_overdue Due today & overdue
Week-based:
Condition What it matches
this_week Current week
last_week Previous week
next_week Upcoming week
next_7_days Next 7 days
Month-based:
Condition What it matches
this_month Current month
last_month Previous month
next_month Upcoming month
next_30_days Next 30 days
Null or Empty Date Fields:
Condition What it matches
unscheduled No date set
Status Presets (Projects and Custom Modules only)

Includes predefined conditions that group records based on their status, such as open or closed.

Condition Description
all_open All open statuses
all_closed All closed statuses
Note
  • To filter by a specific status, use is or is_not with the status ID. Example: "value": ["4000000012345"].
User Conditions

Used for fields related to users, including assignments, reporting structure, and user-specific states. (requires ZPUID in the value array):

Condition API Value What it does
Is is Records assigned to the given user(s). Multiple values = OR logic
Is not is_not Excludes records assigned to the given user(s)
Empty Condition

Used to identify fields that do not have any value assigned.

Condition Description
is_empty Field has no value
Note
  • Useful for finding incomplete records, such as tasks with no due date or unassigned tasks.
  • For date fields, use unscheduled instead of is_empty to filter records with no date set.

Text: Contains

{
  "criteria": [
    {
      "field_name": "name",
      "criteria_condition": "contains",
      "value": ["review"]
    }
  ],
  "pattern": "1"
}

Multi-Value IS

{
  "criteria": [
    {
      "field_name": "waiting_for",
      "criteria_condition": "is",
      "value": ["frontend", "backend"]
    }
  ],
  "pattern": "1"
}

Date: Between

{
  "criteria": [
    {
      "field_name": "start_date",
      "criteria_condition": "between",
      "value": ["2024-11-01", "2024-11-30"]
    }
  ],
  "pattern": "1"
}

Numeric: Greater Than

{
  "criteria": [
    {
      "field_name": "percentage_completion",
      "criteria_condition": "greater_than",
      "value": ["50"]
    }
  ],
  "pattern": "1"
}

Date Preset: Today

{
  "criteria": [
    {
      "field_name": "end_date",
      "criteria_condition": "today"
    }
  ],
  "pattern": "1"
}

Date Preset: This Week

{
  "criteria": [
    {
      "field_name": "end_date",
      "criteria_condition": "this_week"
    }
  ],
  "pattern": "1"
}

Date Preset: This Month

{
  "criteria": [
    {
      "field_name": "end_date",
      "criteria_condition": "this_month"
    }
  ],
  "pattern": "1"
}

Status Preset: All Open

{
  "criteria": [
    {
      "field_name": "status",
      "criteria_condition": "all_open"
    }
  ],
  "pattern": "1"
}

User: Is

{
  "criteria": [
    {
      "field_name": "assignee",
      "criteria_condition": "is",
      "value": ["4000000006061"]
    }
  ],
  "pattern": "1"
}

Overdue + Assigned to Me

{
  "criteria": [
    {
      "field_name": "due_date",
      "criteria_condition": "is",
      "value": ["2026-12-31"]
    },
    {
      "field_name": "owner",
      "criteria_condition": "is",
      "value": ["4000000006061"]
    }
  ],
  "pattern": "1 AND 2"
}

Empty Field Check

{
  "criteria": [
    {
      "field_name": "description",
      "criteria_condition": "is_empty"
    }
  ],
  "pattern": "1"
}

Unscheduled Date Field

{
  "criteria": [
    {
      "field_name": "end_date",
      "criteria_condition": "unscheduled"
    }
  ],
  "pattern": "1"
}
Frequently Used Filters

Ready-made filter payloads for the most common requests. Copy a payload, URL-encode it, and pass it as the filter query parameter.

Common Filters

These filters work across modules such as tasks, issues, and custom modules.

Filter by Open Status

Returns all open tasks in a single request.

Uses status with the custom_condition operator and the ${ALL_OPEN} value.

Filter by Open Status

{
  "criteria": [
    {
      "field_name": "status",
      "criteria_condition": "custom_condition",
      "value": ["${ALL_OPEN}"]
    }
  ],
  "pattern": "1"
}
Filter by Closed Status

Returns all closed tasks in a single request.

Uses status with the custom_condition operator and the ${ALL_CLOSED} value.

Filter by Closed Status

{
  "criteria": [
    {
      "field_name": "status",
      "criteria_condition": "custom_condition",
      "value": ["${ALL_CLOSED}"]
    }
  ],
  "pattern": "1"
}
Filter by Status

Returns tasks in a specific status.

Uses status with the is condition and the status ID as the value.

Filter by Status

{
  "criteria": [
    {
      "field_name": "status",
      "criteria_condition": "is",
      "value": ["268026000001877009"]
    }
  ],
  "pattern": "1"
}
Filter by Owner

Returns tasks owned by a specific user.

Uses owner with the is condition and the user's ZPUID as the value.

Filter by Owner

{
  "criteria": [
    {
      "field_name": "owner",
      "criteria_condition": "is",
      "value": ["268026000002340076"]
    }
  ],
  "pattern": "1"
}
Filter by Name

Returns tasks whose name contains the given text.

Uses name with the contains condition and the search text as the value.

Filter by Name

{
  "criteria": [
    {
      "field_name": "name",
      "criteria_condition": "contains",
      "value": ["test"]
    }
  ],
  "pattern": "1"
}
Filter by Created Time

Returns tasks created after a specific point in time.

Uses created_time with the greater_than condition and a YYYY-MM-DD value.

Filter by Created Time

{
  "criteria": [
    {
      "field_name": "created_time",
      "criteria_condition": "greater_than",
      "value": ["2026-03-01"]
    }
  ],
  "pattern": "1"
}
Filter by Last Modified Time

Returns tasks last updated after a specific date.

Uses last_updated_time with the greater_than condition and a YYYY-MM-DD value.

Filter by Last Modified Time

{
  "criteria": [
    {
      "field_name": "last_updated_time",
      "criteria_condition": "greater_than",
      "value": ["2026-03-01"]
    }
  ],
  "pattern": "1"
}
Task Filters

These filters are available in the Tasks module only.

Filter by Subtask

Returns only subtasks (tasks that have a parent task).

Uses has_parents with value true. Set false to return only top-level tasks. Accepts "true" / "false" or "1" / "0".

Filter by Subtask

{
  "criteria": [
    {
      "field_name": "has_parents",
      "criteria_condition": "is",
      "value": ["true"]
    }
  ],
  "pattern": "1"
}
Filter by Parent Task

Returns the subtasks of a specific parent task.

Uses parent_task with the is condition and the parent task ID as the value.

Filter by Parent Task

{
  "criteria": [
    {
      "field_name": "parent_task",
      "criteria_condition": "is",
      "value": ["268026000003251123"]
    }
  ],
  "pattern": "1"
}
Filter by Task List

Returns tasks that belong to a task list whose name contains the given text.

Uses module_name set to tasklist to filter on the related module's name field.

Filter by Task List

{
  "criteria": [
    {
      "module_name": "tasklist",
      "field_name": "name",
      "criteria_condition": "contains",
      "value": ["Codex"]
    }
  ],
  "pattern": "1"
}
API Authentication - Overview

Zoho Projects APIs use OAuth 2.0 for authentication. This page gives you an overview of the authentication process. For complete details on OAuth 2.0 flows, registration, token management, and more, refer to Zoho OAuth 2.0 documentation.

How it works

To access Zoho Projects APIs, your application needs an access token obtained through one of the OAuth 2.0 flows. At a high level, the steps are:

  1. Register your application in the Zoho API console.
  2. Get consent from user to access their data and obtain an access token.
  3. Call Zoho Projects APIs using the access token.
Token expiry

Access tokens expire periodically. The expiry duration is returned as expires_in (seconds) in the access token response.

To maintain uninterrupted access, you can request for an optional refresh token, store it, and use it to generate new access tokens as needed.

Token lifecycle
  • Access tokens are required for every API request.
  • Refresh tokens can be used to generate new access tokens without requiring user re-authorization.
  • Users can revoke an application's access at any time, which invalidates the associated tokens.

For more details on token management, refer to Zoho OAuth 2.0 documentation.

Different OAuth flows for different app types

Zoho supports OAuth flows for different application types (server-based, client-based, mobile & desktop-based, limited input devices, and self client). You can choose the flow that matches your application.

For detailed information, refer to the OAuth documentation.

Multi DC support

Zoho operates data centers in multiple regions. If your application serves users across regions, you must enable Multi DC support in the API console and use region-specific endpoints for both OAuth and Zoho Projects API calls.

See Multi-DC Support.

Scopes

Zoho Projects APIs require OAuth scopes to define the level of access your application needs. When requesting for access token, request only the scopes your application requires. These will be displayed to the users when asking for consent.

Scope Description
ZohoProjects.projects.READ Access project data (read-only)
ZohoProjects.projects.ALL Full access to projects
ZohoProjects.tasks.ALL Full access to tasks
ZohoProjects.timesheets.ALL Full access to time logs

To request multiple scopes, separate them with commas:

scope=ZohoProjects.projects.READ,ZohoProjects.tasks.ALL

For more details about scope format, see OAuth Scopes.

Making API calls with access token

To authenticate your API calls, include the access token in the Authorization header of every API request with the prefix Bearer.

Syntax
Authorization: Bearer {access-token-value}
Example
curl -X GET "https://projects.zoho.com/api/v3/portals" -H "Authorization: Bearer 1000.abc123def456..."
Self-Client option

Use this method to generate the organization-specific grant token if your application does not have a domain and a redirect URL. You can also use this option when your application is a standalone server-side application performing a back-end job.

  1. Go to Zoho Developer Console and log in with your Zoho Projects username and password.
  2. Choose Self Client from the list of client types, and click Create Now.
  3. Click OK in the pop up to enable a self client for your account.
  4. Now, your client ID and client secret are displayed under the Client Secret tab.
The Client Secret tab of a self client, showing the generated client ID and client secret.
  1. Click the Generate Code tab and enter the required scope separated by commas. Refer to our list of Scopes, for more details. The system throws an 'Enter a valid scope' error when you enter one or more incorrect scopes.
  2. Select the Time Duration for which the grant token is valid. Please note that after this time, the grant token expires.
  3. Enter a description and click Create.
The Generate Code tab, with the scope, time duration and description fields filled in.
  1. The organization-specific grant token code for the specified scope is displayed. Copy the grant token.
The generated grant token code displayed for the requested scope, ready to copy.
API endpoints by data center

When making API calls, you must use the base URL corresponding to your user's data center. The access token response identifies the user's data center through the location and api_domain values - use it to pick the matching Zoho Projects base URL from the table below.

Data center API base URL
United States (US) https://projects.zoho.com
European Union (EU) https://projects.zoho.eu
India (IN) https://projects.zoho.in
Australia (AU) https://projects.zoho.com.au
Japan (JP) https://projects.zoho.jp
Canada (CA) https://projects.zohocloud.ca
China (CN) https://projects.zoho.com.cn
Saudi Arabia (SA) https://projects.zoho.sa
United Kingdom (UK) https://projects.zoho.uk
United Arab Emirates (UAE) https://projects.zoho.ae
Singapore (SG) https://projects.zoho.sg
Important

Never hardcode a single region's URL. Resolve the user's data center from the location / api_domain value in the access token response, then use the corresponding Zoho Projects base URL from the table above. See Multi-DC Support.

AI Tools
ChatGPT Open in ChatGPT ↗ Open in ChatGPT to ask questions about this page
Claude Open in Claude ↗ Open in Claude to ask questions about this page
Copy as Markdown Copy this page as markdown to use with AI assistants
View as Markdown ↗ Open this page as markdown in a new tab
Copy OpenAPI Spec Copy the OpenAPI YAML to the clipboard
View as YAML ↗ Open the OpenAPI spec in a new tab
Download YAML Save the OpenAPI spec as a .yaml file