When you're building a customer portal or self-service integration, you need a way for end users to create and view tickets without giving them full admin access. The Zendesk Requests API is designed exactly for this purpose.
The Requests API provides an end user's perspective on tickets. Users can create requests, view their ticket history, and add comments, all while only seeing public information. It's the secure, limited-access alternative to the full Tickets API.
If you're looking to automate support without building custom API integrations, tools like eesel AI can handle the full spectrum of support automation, from ticket routing to AI-powered responses. eesel integrates directly with Zendesk and learns from your existing tickets and documentation. But if you need direct API access for custom integrations, this guide will walk you through everything you need to know.
What you'll need
Before you start making API calls, make sure you've got:
- A Zendesk account with appropriate permissions (admin access for setting up API tokens)
- API token or OAuth credentials (we'll cover how to generate these)
- Basic familiarity with REST APIs (you should understand GET, POST, and PUT requests)
- A development environment (cURL, Python, or Node.js will work fine)
Understanding the Requests API
What is a request?
In Zendesk, a request is an end user's perspective on a ticket. While agents see the full ticket with internal notes, custom fields, and private comments, end users only see public comments and a limited set of fields.
Here's how the JSON format looks for a request:
{
"id": 35436,
"subject": "Help, my printer is on fire!",
"description": "The fire is very colorful.",
"status": "open",
"priority": "normal",
"type": "problem",
"requester_id": 1462,
"created_at": "2009-07-20T22:55:29Z",
"updated_at": "2011-05-05T10:38:52Z"
}
Key properties include:
subject(required) - The subject line visible to the end userdescription- Read-only first comment on the requeststatus- new, open, pending, hold, solved, or closedpriority- low, normal, high, or urgenttype- question, incident, problem, or task
Source: Zendesk Requests API Reference
Requests vs Tickets API: Which should you use?
This is a critical decision that'll affect how your integration behaves. Here's the breakdown:
| Factor | Requests API | Tickets API |
|---|---|---|
| Who can use it | End users, admins (as end users) | Agents and admins only |
| Visibility | Public comments only | Full ticket access |
| Agent Copilot | Works correctly | May not trigger |
| Use case | Customer portals, self-service | Internal tools, admin functions |
The Agent Copilot issue is important. When you create a ticket via the Tickets API on behalf of an end user, Zendesk interprets it as created by an agent. This means Agent Copilot won't fire because it's waiting for a customer reply that never comes. Using the Requests API ensures tickets behave exactly like those created through email or messaging.
Source: Internal Note - API Requests and Agent Copilot
Authentication methods
End user authentication
End users can authenticate using their own credentials. When using the Requests endpoint, admins and agents are treated as end users, so they see the same limited view.
API Token Authentication:
curl https://your-subdomain.zendesk.com/api/v2/requests.json \
-u user@example.com/token:your_api_token_here
Important note: An end user won't be able to view their requests if they've added an email identity after September 17, 2017, and didn't verify the email address. The API returns a 403 response in this case.
Source: Zendesk Requests API Reference
Making requests on behalf of end users (admin impersonation)
Sometimes you'll need an admin to create tickets for end users. This requires OAuth with an impersonate scope.
Step 1: Create an OAuth client in Admin Center (Apps and integrations > APIs > OAuth clients)
Step 2: Request an access token with the "impersonate" scope:
curl https://{subdomain}.zendesk.com/api/v2/oauth/tokens.json \
-H "Content-Type: application/json" \
-d '{
"token": {
"client_id": "your_client_id",
"scopes": ["impersonate", "write"]
}
}' \
-X POST -v -u {email_address}/token:{api_token}
Step 3: Include the X-On-Behalf-Of header in your requests:
curl https://z3napi.zendesk.com/api/v2/requests.json \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "X-On-Behalf-Of: customer@example.com" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"request": {
"subject": "Help request",
"comment": {"body": "I need assistance with my order"}
}
}'
Important: The impersonated end user must have an existing user profile. Otherwise, the request will fail with an invalid_token error.
Source: Making API requests on behalf of end users
Anonymous requests
If your Zendesk admin has enabled it, you can create requests without any authentication. This is useful for public contact forms.
Requirements:
- Anonymous requests must be enabled in Admin Center
- Include a
requesterobject with at least a name
{
"request": {
"requester": {"name": "Anonymous customer"},
"subject": "Help!",
"comment": {"body": "My printer is on fire!"}
}
}
Rate limits: Anonymous requests are limited to 5 per hour for trial accounts.
Source: Creating and managing requests
Key API endpoints
List requests
Retrieve all requests for the authenticated user:
GET /api/v2/requests
Parameters:
page- Pagination (supports offset or cursor-based)per_page- Number of records per pagesort_by- "updated_at" or "created_at"sort_order- "asc" or "desc"
Create a request
Create a new ticket from an end user's perspective:
POST /api/v2/requests
Required fields:
subject- The ticket subjectcomment- Object withbodycontaining the description
Optional fields:
requester- For anonymous requests (object with name, email)collaborators- Array of user IDs or emails to CCcustom_fields- Array of custom field valuestags- Array of tags to apply
Update a request
Add comments or mark a request as solved:
PUT /api/v2/requests/{id}
Writable properties:
comment- Add a new commentsolved- Set to true to mark as solved (only ifcan_be_solved_by_meis true)additional_collaborators- Add CCs to the request
List comments
View the conversation history:
GET /api/v2/requests/{request_id}/comments
By default, comments are sorted by creation date in ascending order.
Source: Zendesk Requests API Reference
Code examples
Creating a request with cURL
#!/bin/bash
SUBDOMAIN="your-subdomain"
EMAIL="admin@example.com"
TOKEN="your_api_token"
curl "https://${SUBDOMAIN}.zendesk.com/api/v2/requests.json" \
-u "${EMAIL}/token:${TOKEN}" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"request": {
"subject": "Order status inquiry",
"comment": {
"body": "I placed an order last week and would like to check the status. My order number is #12345."
},
"collaborators": ["spouse@example.com"]
}
}'
Creating a request with Python
import requests
import json
subdomain = "your-subdomain"
email = "admin@example.com"
api_token = "your_api_token"
url = f"https://{subdomain}.zendesk.com/api/v2/requests.json"
payload = {
"request": {
"subject": "Technical support needed",
"comment": {
"body": "I'm having trouble logging into my account. Can you help?"
}
}
}
auth = (f"{email}/token", api_token)
headers = {"Content-Type": "application/json"}
try:
response = requests.post(url, json=payload, auth=auth, headers=headers)
response.raise_for_status()
data = response.json()
print(f"Request created successfully!")
print(f"Ticket ID: {data['request']['id']}")
print(f"Status: {data['request']['status']}")
except requests.exceptions.HTTPError as err:
print(f"HTTP Error: {err}")
print(f"Response: {response.text}")
except Exception as err:
print(f"Error: {err}")
Creating a request with Node.js
const axios = require('axios');
const config = {
subdomain: 'your-subdomain',
email: 'admin@example.com',
apiToken: 'your_api_token'
};
async function createRequest() {
const url = `https://${config.subdomain}.zendesk.com/api/v2/requests.json`;
const payload = {
request: {
subject: 'Billing question',
comment: {
body: 'I was charged twice for my subscription this month. Please help resolve this.'
}
}
};
try {
const response = await axios.post(url, payload, {
auth: {
username: `${config.email}/token`,
password: config.apiToken
},
headers: {
'Content-Type': 'application/json'
}
});
console.log('Request created successfully!');
console.log(`Ticket ID: ${response.data.request.id}`);
console.log(`Status: ${response.data.request.status}`);
} catch (error) {
console.error('Error creating request:', error.response?.data || error.message);
}
}
createRequest();
Common errors and troubleshooting
403 Forbidden
This is the most common error when working with the Requests API. Common causes:
- Unverified email: The end user added an email after September 17, 2017, without verifying it
- Insufficient permissions: Trying to access endpoints not allowed for end users
- Missing impersonate scope: Attempting to make requests on behalf of users without proper OAuth scope
Solution: Verify the user's email address in Zendesk admin, or ensure you're using the correct authentication method for your use case.
401 Unauthorized
- Invalid API token or OAuth credentials
- Token has expired (OAuth tokens have limited lifespans)
- User account is suspended or deleted
Solution: Double-check your credentials and regenerate tokens if necessary.
429 Rate Limit Exceeded
- Standard API: 700 requests per minute
- Anonymous requests: 5 per hour (trial accounts)
Solution: Implement exponential backoff in your code. When you receive a 429, wait before retrying:
import time
def make_request_with_retry(url, payload, auth, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, auth=auth)
response.raise_for_status()
return response
except requests.exceptions.HTTPError as err:
if response.status_code == 429:
wait_time = (2 ** attempt) # Exponential backoff
print(f"Rate limited. Waiting {wait_time} seconds...")
time.sleep(wait_time)
else:
raise
raise Exception("Max retries exceeded")
Agent Copilot not firing
If you're using Zendesk's Agent Copilot and it's not suggesting responses for tickets created via API, you're likely using the Tickets API instead of the Requests API.
Solution: Switch to the Requests API (POST /api/v2/requests.json) instead of the Tickets API (POST /api/v2/tickets.json).
Source: Internal Note - API Requests and Agent Copilot
Best practices
Use the Requests API for end-user facing integrations
If you're building a customer portal, self-service widget, or any interface where end users create tickets, always use the Requests API. This ensures:
- Proper Agent Copilot behavior
- Correct first reply time calculations
- Consistent ticket lifecycle with email-created tickets
Handle rate limits gracefully
Always implement retry logic with exponential backoff. Zendesk's API is shared across all customers, and aggressive polling can get your integration rate-limited or blocked.
Validate email verification status
Before allowing users to view their requests, verify their email is confirmed. You can check this via the Users API and prompt them to verify if needed.
Store credentials securely
Don't hardcode API tokens in your frontend code or commit them to version control. Use environment variables or secure secret management systems.
Consider no-code alternatives
Building and maintaining API integrations takes significant development resources. If your goal is to automate support responses rather than build custom portals, consider tools like eesel AI that integrate directly with Zendesk and provide AI-powered automation without writing code. eesel AI doesn't require complex configuration you simply invite it to your team and it learns your business in minutes.

We offer:
- AI Agent that handles frontline support autonomously
- AI Copilot that drafts replies for agents to review
- AI Triage that tags, routes, and prioritizes tickets automatically
- One-click integration with Zendesk (no API development required)
Source: eesel AI Products
Start building with the Zendesk Requests API
The Zendesk Requests API gives you a secure way to let end users interact with your support system. By understanding the difference between Requests and Tickets APIs, implementing proper authentication, and following best practices, you can build robust self-service integrations.
Key takeaways:
- Use the Requests API for end-user facing integrations
- Implement OAuth with impersonate scope when admins need to act on behalf of users
- Handle rate limits and errors gracefully
- Test thoroughly before deploying to production
For more details, check out the official Zendesk Requests API documentation.
If you're looking to automate support without the development overhead, explore how eesel AI can help. Our AI agents integrate directly with Zendesk, learn from your existing documentation and past tickets, and can handle up to 81% of frontline support autonomously.
Frequently Asked Questions
Share this post

Article by
Stevia Putri
Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.



