Data & analysis

zoho-recruit

Try it

Read and write Zoho Recruit candidates, job openings, and interviews through managed OAuth.

What it does

Connects to the Zoho Recruit API through a managed OAuth proxy at api.maton.ai. Supports full CRUD on Candidates and Job Openings, plus create and read on Interviews, with criteria-based search, pagination up to 200 records per page, and field selection. Authentication uses a Maton API key in the Authorization header; the OAuth token is injected automatically. Multiple Zoho Recruit accounts can be disambiguated with the Maton-Connection header. All create, update, and delete operations require explicit user confirmation before execution.

When to use it

  • Listing or paginating candidates with field selection
  • Searching candidates by criteria, email, or phone
  • Creating and updating job openings
  • Scheduling interviews linked to candidates and postings

The skill document

Zoho Recruit

Access the Zoho Recruit API with managed OAuth authentication. Manage candidates, job openings, interviews, applications, and recruitment workflows with full CRUD operations.

Quick Start

# List all candidates
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates?per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://api.maton.ai/zoho-recruit/{native-api-path}

Maton proxies requests to recruit.zoho.com and automatically injects your OAuth token.

Authentication

All requests require the Maton API key in the Authorization header:

Authorization: Bearer $MATON_API_KEY

Environment Variable: Set your API key as MATON_API_KEY:

export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key

Connection Management

Manage your Zoho Recruit OAuth connections at https://api.maton.ai.

List Connections

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=zoho-recruit&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'zoho-recruit'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "{connection_id}",
    "status": "ACTIVE",
    "creation_time": "2026-02-06T07:48:59.474215Z",
    "last_updated_time": "2026-02-06T07:57:52.950167Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "zoho-recruit",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple Zoho Recruit connections, specify which one to use with the Maton-Connection header:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If you have multiple connections, always include this header to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to candidates, job openings, interviews, and recruitment workflows within the connected Zoho Recruit account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.

API Reference

Modules

List All Modules

Get a list of all available modules in your Zoho Recruit account.

GET /zoho-recruit/recruit/v2/settings/modules

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/settings/modules')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Candidates

List Candidates

GET /zoho-recruit/recruit/v2/Candidates

Query Parameters:

ParameterTypeDefaultDescription
fieldsstring-Comma-separated field API names
sort_orderstring-asc or desc
sort_bystring-Field API name to sort by
convertedstring-true, false, or both
approvedstring-true, false, or both
pageinteger1Page number
per_pageinteger200Records per page (max 200)

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates?per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "data": [
    {
      "id": "846336000000552208",
      "First_Name": "Christina",
      "Last_Name": "Palaskas",
      "Email": "c.palaskas@example.com",
      "Candidate_Status": "Converted - Employee",
      "Current_Employer": "Chandlers",
      "Current_Job_Title": "Technical Consultant",
      "Experience_in_Years": 3,
      "Skill_Set": "Communication, Presentation, Customer service",
      "Candidate_Owner": {
        "name": "Byungkyu Park",
        "id": "846336000000549541"
      }
    }
  ],
  "info": {
    "per_page": 10,
    "count": 1,
    "page": 1,
    "more_records": false
  }
}

Get Candidate by ID

GET /zoho-recruit/recruit/v2/Candidates/{record_id}

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates/846336000000552208')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Search Candidates

GET /zoho-recruit/recruit/v2/Candidates/search?criteria={criteria}

Query Parameters:

ParameterTypeDescription
criteriastringSearch criteria (e.g., (Last_Name:contains:Smith))
emailstringSearch by email
phonestringSearch by phone
wordstringGlobal word search
pageintegerPage number
per_pageintegerRecords per page

Search Operators:

  • Text: equals, not_equal, starts_with, ends_with, contains, not_contains, in
  • Date/Number: equals, not_equal, greater_than, less_than, greater_equal, less_equal, between

Example:

python <<'EOF'
import urllib.request, os, json
import urllib.parse
criteria = urllib.parse.quote('(Candidate_Status:equals:Active)')
req = urllib.request.Request(f'https://api.maton.ai/zoho-recruit/recruit/v2/Candidates/search?criteria={criteria}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Candidate

POST /zoho-recruit/recruit/v2/Candidates
Content-Type: application/json

{
  "data": [
    {
      "First_Name": "John",
      "Last_Name": "Doe",
      "Email": "john.doe@example.com",
      "Phone": "555-123-4567",
      "Current_Job_Title": "Software Engineer"
    }
  ]
}

Example:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({
    "data": [{
        "First_Name": "John",
        "Last_Name": "Doe",
        "Email": "john.doe@example.com",
        "Phone": "555-123-4567"
    }]
}).encode()
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "data": [
    {
      "code": "SUCCESS",
      "status": "success",
      "message": "record added",
      "details": {
        "id": "846336000000600001",
        "Created_Time": "2026-02-06T10:00:00-08:00",
        "Created_By": {
          "name": "User Name",
          "id": "846336000000549541"
        }
      }
    }
  ]
}

Update Candidate

PUT /zoho-recruit/recruit/v2/Candidates/{record_id}
Content-Type: application/json

{
  "data": [
    {
      "Current_Job_Title": "Senior Software Engineer"
    }
  ]
}

Example:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({
    "data": [{
        "Current_Job_Title": "Senior Software Engineer"
    }]
}).encode()
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Candidates/846336000000552208', data=data, method='PUT')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Delete Candidates

DELETE /zoho-recruit/recruit/v2/Candidates?ids={record_id1},{record_id2}

Job Openings

List Job Openings

GET /zoho-recruit/recruit/v2/Job_Openings

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Job_Openings?per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "data": [
    {
      "id": "846336000000552093",
      "Posting_Title": "Senior Accountant (Sample)",
      "Job_Opening_Status": "Waiting for approval",
      "Date_Opened": "2026-01-21",
      "Target_Date": "2026-02-20",
      "Industry": "Accounting",
      "City": "Tallahassee",
      "No_of_Candidates_Hired": 0,
      "No_of_Candidates_Associated": 0
    }
  ],
  "info": {
    "per_page": 10,
    "count": 1,
    "page": 1,
    "more_records": false
  }
}

Get Job Opening by ID

GET /zoho-recruit/recruit/v2/Job_Openings/{record_id}

Create Job Opening

POST /zoho-recruit/recruit/v2/Job_Openings
Content-Type: application/json

{
  "data": [
    {
      "Posting_Title": "Software Engineer",
      "Job_Opening_Status": "In-progress",
      "Date_Opened": "2026-02-01",
      "Target_Date": "2026-03-01"
    }
  ]
}

Update Job Opening

PUT /zoho-recruit/recruit/v2/Job_Openings/{record_id}
Content-Type: application/json

Delete Job Openings

DELETE /zoho-recruit/recruit/v2/Job_Openings?ids={record_id1},{record_id2}

Interviews

List Interviews

GET /zoho-recruit/recruit/v2/Interviews

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Interviews?per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Interview by ID

GET /zoho-recruit/recruit/v2/Interviews/{record_id}

Create Interview

POST /zoho-recruit/recruit/v2/Interviews
Content-Type: application/json

{
  "data": [
    {
      "Interview_Name": "Technical Interview",
      "Candidate_Name": {"id": "846336000000552208"},
      "Posting_Title": {"id": "846336000000552093"},
      "Start_DateTime": "2026-02-10T10:00:00-08:00",
      "End_DateTime": "2026-02-10T11:00:00-08:00"
    }
  ]
}

Departments

List Departments

GET /zoho-recruit/recruit/v2/Departments

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-recruit/recruit/v2/Departments?per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Applications

List Applications

GET /zoho-recruit/recruit/v2/Applications

Generic Record Operations

All modules support the same CRUD operations:

# List records
GET /zoho-recruit/recruit/v2/{module_api_name}

# Get record by ID
GET /zoho-recruit/recruit/v2/{module_api_name}/{record_id}

# Create records
POST /zoho-recruit/recruit/v2/{module_api_name}

# Update records
PUT /zoho-recruit/recruit/v2/{module_api_name}/{record_id}

# Delete records
DELETE /zoho-recruit/recruit/v2/{module_api_name}?ids={id1},{id2}

# Search records
GET /zoho-recruit/recruit/v2/{module_api_name}/search?criteria={criteria}

Available Modules

ModuleAPI NameDescription
CandidatesCandidatesJob candidates
Job OpeningsJob_OpeningsOpen positions
ApplicationsApplicationsJob applications
InterviewsInterviewsScheduled interviews
DepartmentsDepartmentsCompany departments
ClientsClientsClient companies
ContactsContactsContact persons
CampaignsCampaignsRecruitment campaigns
ReferralsReferralsEmployee referrals
TasksTasksTo-do items
EventsEventsCalendar events
VendorsVendorsExternal vendors

Pagination

Zoho Recruit uses page-based pagination:

GET /zoho-recruit/recruit/v2/{module_api_name}?page=1&per_page=200
  • page: Page number (default: 1)
  • per_page: Records per page (default: 200, max: 200)

Response includes pagination info:

{
  "data": [...],
  "info": {
    "per_page": 200,
    "count": 50,
    "page": 1,
    "more_records": false
  }
}

Code Examples

JavaScript

const response = await fetch(
  'https://api.maton.ai/zoho-recruit/recruit/v2/Candidates?per_page=10',
  {
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`
    }
  }
);
const data = await response.json();

Python

import os
import requests

response = requests.get(
    'https://api.maton.ai/zoho-recruit/recruit/v2/Candidates',
    headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
    params={'per_page': 10}
)
data = response.json()

Notes

  • Record IDs are numeric strings (e.g., 846336000000552208)
  • Maximum 200 records per GET request
  • Maximum 100 records per POST/PUT request
  • Maximum 100 records per DELETE request
  • Module API names are case-sensitive (e.g., Job_Openings, not job_openings)
  • Last_Name is mandatory for Candidates
  • Date format: yyyy-MM-dd
  • DateTime format: yyyy-MM-ddTHH:mm:ss±HH:mm (ISO 8601)
  • Lookup fields use JSON objects with id and optionally name
  • IMPORTANT: When using curl commands, use curl -g when URLs contain special characters
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

StatusMeaning
400Missing Zoho Recruit connection or invalid request
401Invalid or missing Maton API key
429Rate limited
4xx/5xxPassthrough error from Zoho Recruit API

Common Error Codes

CodeDescription
INVALID_DATAInvalid field value
MANDATORY_NOT_FOUNDRequired field missing
DUPLICATE_DATADuplicate record detected
INVALID_MODULEInvalid module API name
NO_PERMISSIONInsufficient permissions

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with zoho-recruit. For example:
  • Correct: https://api.maton.ai/zoho-recruit/recruit/v2/Candidates
  • Incorrect: https://api.maton.ai/recruit/v2/Candidates

Resources

Questions people ask

How is authentication handled?
Set MATON_API_KEY and send it as a Bearer token in the Authorization header. Maton injects the Zoho Recruit OAuth token automatically; you do not manage Zoho tokens yourself.
Can I target a specific Zoho Recruit account when I have several?
Yes. Create separate connections at api.maton.ai and pass the connection ID in the Maton-Connection header to route each request to the intended account.
Are write operations safe to run?
Every create, update, and delete call requires explicit user approval before it is executed, so no records are changed silently.

Related skills

Send, search, and manage Zoho Mail messages, folders, and labels through OAuth-proxied API calls.

520 installs8 stars

Read and modify Zoho People HR records — employees, departments, leave, and custom forms — via managed OAuth.

481 installs3 stars

Read and write Zoho CRM records through a Maton-managed OAuth proxy, with user confirmation on every create, update, and delete.

463 installs6 stars

Read and manage Zoho Calendar calendars and events through a managed OAuth API gateway.

486 installs4 stars

Manage Zoho Bookings appointments, services, staff, and workspaces via managed OAuth through Maton's API proxy.

39 installs

Read and write Zoho Projects API V3 resources through a managed OAuth gateway with explicit user confirmation on writes.

35 installs