| name | zendesk |
| description | Zendesk Support REST API for managing tickets, users, organizations, and support operations. Use this skill to create tickets, manage users, search, and automate customer support workflows. |
| vm0_secrets | ZENDESK_API_TOKEN |
| vm0_vars | ZENDESK_EMAIL, ZENDESK_SUBDOMAIN |
Zendesk API
Manage customer support tickets, users, organizations, and support operations via the Zendesk Support REST API.
Official docs:
https://developer.zendesk.com/api-reference/
When to Use
Use this skill when you need to:
- Manage tickets - Create, update, search, and close support tickets
- Handle users - Create end-users, agents, and manage user profiles
- Organize accounts - Manage organizations and their members
- Support groups - Create and manage agent groups for ticket routing
- Search data - Find tickets, users, and organizations with powerful search
- Bulk operations - Create or update multiple resources at once
- Automate support - Build integrations and automate workflows
- Track metrics - Access ticket data for reporting and analytics
Prerequisites
Getting Your API Token
⚠️ Important: You must enable Token Access before creating tokens.
- Log in to Zendesk Admin Center (admin access required)
- Navigate to Apps and integrations → APIs → Zendesk API
- Click the Settings tab
- Under Token Access, toggle Enabled (this is required!)
- Click Add API token
- Enter a description (e.g., "VM0 Integration")
- Click Save and copy the token immediately (shown only once)
export ZENDESK_EMAIL="your-email@company.com"
export ZENDESK_API_TOKEN="your_api_token"
export ZENDESK_SUBDOMAIN="yourcompany"
Find Your Subdomain
Your subdomain is in your Zendesk URL:
https://yourcompany.zendesk.com
^^^^^^^^^^^
subdomain
Verify Token
Test your credentials:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '{count: .count, tickets: .tickets | length}
Expected response: Ticket count and list
Alternative verification (list users):
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.users[] | {id, name, email, role}
Note: The /users/me.json endpoint may return anonymous user for API token authentication. Use /tickets.json or /users.json to verify token validity.
✅ This skill has been tested and verified with a live Zendesk workspace. All core endpoints work correctly.
Important: When using
$VARin a command that pipes to another command, wrap the command containing$VARinbash -c '...'. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq .
How to Use
All examples assume environment variables are set.
Base URL: https://{subdomain}.zendesk.com/api/v2/
Authentication: API Token via -u flag
-u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"
Note: The -u flag automatically handles Base64 encoding for you.
Core APIs
1. List Tickets
Get all tickets (paginated):
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.tickets[] | {id, subject, status, priority}
With pagination:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json?page=1&per_page=50" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq .
2. Get Ticket
Retrieve a specific ticket:
TICKET_ID="123"
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq .
3. Create Ticket
Create a new support ticket:
Write to /tmp/zendesk_request.json:
{
"ticket": {
"subject": "My printer is on fire!",
"comment": {
"body": "The smoke is very colorful."
},
"priority": "urgent"
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
Create ticket with more details:
Write to /tmp/zendesk_request.json:
{
"ticket": {
"subject": "Need help with account",
"comment": {
"body": "I cannot access my account settings."
},
"priority": "high",
"status": "open",
"type": "problem",
"tags": ["account", "access"]
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
4. Update Ticket
Update an existing ticket:
TICKET_ID="123"
Write to /tmp/zendesk_request.json:
{
"ticket": {
"status": "solved",
"comment": {
"body": "Issue has been resolved. Thank you!",
"public": true
}
}
}
Then run:
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
Change priority and assignee:
TICKET_ID="123"
ASSIGNEE_ID="456"
Write to /tmp/zendesk_request.json:
{
"ticket": {
"priority": "high",
"assignee_id": ASSIGNEE_ID_PLACEHOLDER
}
}
Then run:
sed -i '' "s/ASSIGNEE_ID_PLACEHOLDER/${ASSIGNEE_ID}/" /tmp/zendesk_request.json
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
5. Delete Ticket
Permanently delete a ticket:
TICKET_ID="123"
curl -s -X DELETE "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"
6. Create Multiple Tickets
Bulk create tickets:
Write to /tmp/zendesk_request.json:
{
"tickets": [
{
"subject": "Ticket 1",
"comment": {
"body": "First ticket"
}
},
{
"subject": "Ticket 2",
"comment": {
"body": "Second ticket"
}
}
]
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/create_many.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
7. List Users
Get all users:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.users[] | {id, name, email, role}
8. Get Current User
Get authenticated user details:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users/me.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq .
9. Create User
Create an end-user:
Write to /tmp/zendesk_request.json:
{
"user": {
"name": "John Customer",
"email": "john@example.com",
"role": "end-user"
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
Create an agent:
Write to /tmp/zendesk_request.json:
{
"user": {
"name": "Jane Agent",
"email": "jane@company.com",
"role": "agent"
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
10. Update User
Update user information:
USER_ID="456"
Write to /tmp/zendesk_request.json:
{
"user": {
"name": "Updated Name",
"phone": "+1234567890"
}
}
Then run:
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users/${USER_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
11. Search Users
Search for users by query:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/users/search.json?query=john" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.users[] | {id, name, email}
12. List Organizations
Get all organizations:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/organizations.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.organizations[] | {id, name, domain_names}
13. Create Organization
Create a new organization:
Write to /tmp/zendesk_request.json:
{
"organization": {
"name": "Acme Inc",
"domain_names": ["acme.com", "acmeinc.com"],
"details": "Important customer"
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/organizations.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
14. Update Organization
Update organization details:
ORG_ID="789"
Write to /tmp/zendesk_request.json:
{
"organization": {
"name": "Acme Corporation",
"notes": "Premium customer since 2020"
}
}
Then run:
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/organizations/${ORG_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
15. List Groups
Get all agent groups:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/groups.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.groups[] | {id, name}
16. Create Group
Create a new agent group:
Write to /tmp/zendesk_request.json:
{
"group": {
"name": "Support Team"
}
}
Then run:
bash -c 'curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/groups.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
17. Search API
Search for open tickets:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/search.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -G --data-urlencode "query=type:ticket status:open"' | jq '.results[] | {id, subject, status}
Search for high priority tickets:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/search.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -G --data-urlencode "query=type:ticket priority:high"' | jq '.results[]
Search tickets with keywords:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/search.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -G --data-urlencode "query=type:ticket urgent issue"' | jq '.results[]
Search users by email domain:
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/search.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -G --data-urlencode "query=type:user email:*@acme.com"' | jq '.results[]
18. Get Ticket Comments
List all comments on a ticket:
TICKET_ID="123"
bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}/comments.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}"' | jq '.comments[] | {id, body, author_id, public}
19. Assign Ticket to Group
Assign a ticket to a group:
TICKET_ID="123"
GROUP_ID="456"
Write to /tmp/zendesk_request.json:
{
"ticket": {
"group_id": GROUP_ID_PLACEHOLDER
}
}
Then run:
sed -i '' "s/GROUP_ID_PLACEHOLDER/${GROUP_ID}/" /tmp/zendesk_request.json
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
20. Bulk Update Tickets
Update multiple tickets at once:
Write to /tmp/zendesk_request.json:
{
"ticket": {
"status": "solved"
}
}
Then run:
bash -c 'curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/update_many.json?ids=123,124,125" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json' | jq .
Common Workflows
Create Ticket and Assign to Agent
Write to /tmp/zendesk_request.json:
{
"ticket": {
"subject": "New issue",
"comment": {
"body": "Need help"
}
}
}
Then run:
# Create ticket
TICKET_RESPONSE=$(curl -s -X POST "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json)
TICKET_ID=$(echo $TICKET_RESPONSE | jq -r '.ticket.id')
# Assign to agent
ASSIGNEE_ID="789"
Write to /tmp/zendesk_request.json:
{
"ticket": {
"assignee_id": ASSIGNEE_ID_PLACEHOLDER,
"status": "open"
}
}
Then run:
sed -i '' "s/ASSIGNEE_ID_PLACEHOLDER/${ASSIGNEE_ID}/" /tmp/zendesk_request.json
curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/${TICKET_ID}.json" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json
Find and Close Old Tickets
# Search for old open tickets (30+ days)
OLD_TICKETS="$(bash -c 'curl -s "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/search.json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -G --data-urlencode "query=type:ticket status:open created<30"' | jq -r '.results[].id' | paste -sd "," -)"
Write to /tmp/zendesk_request.json:
{
"ticket": {
"status": "closed"
}
}
Then run:
# Bulk close them
curl -s -X PUT "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets/update_many.json?ids=${OLD_TICKETS}" -H "Content-Type: application/json" -u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" -d @/tmp/zendesk_request.json
Search Query Syntax
Ticket Search Operators
type:ticket- Search tickets onlystatus:open- Filter by status (open, pending, solved, closed)priority:high- Filter by priority (low, normal, high, urgent)assignee:name- Find tickets assigned to specific agentgroup:name- Find tickets in specific grouptags:keyword- Search by tagcreated>2024-01-01- Created after datecreated<30- Created in last 30 days"exact phrase"- Search exact text
User Search Operators
type:user- Search users onlyrole:agent- Filter by role (end-user, agent, admin)email:*@domain.com- Search by email domainname:john- Search by name
Combining Operators
Use spaces for AND logic:
query=type:ticket status:open priority:high
Rate Limits
| Plan | Requests/Minute |
|---|---|
| Team | 200 |
| Growth | 400 |
| Professional | 400 |
| Enterprise | 700 |
| Enterprise Plus | 2,500 |
Special Limits:
- Update Ticket: 30 updates per 10 minutes per user per ticket
- Account-wide ceiling: 100,000 requests/minute
Rate Limit Headers
X-Rate-Limit: 700 # Your account's limit
X-Rate-Limit-Remaining: 685 # Requests remaining
Retry-After: 45 # Seconds to wait if exceeded
Handling Rate Limits
# Use curl retry flags
curl "https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json" \
-u "${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}" \
--retry 3 --retry-delay 5
Guidelines
- Enable API token access first: In Admin Center, ensure Token Access is enabled before using tokens
- Always use HTTPS: TLS 1.2+ required
- Monitor rate limits: Check
X-Rate-Limit-Remainingheader - Use bulk operations:
create_many,update_manyendpoints save API calls - Implement exponential backoff: Honor
Retry-Afterheader on 429 responses - Paginate large datasets: Default limit is 100, max per_page is 100
- Secure your tokens: Store in environment variables, never in code
- Use specific searches: Narrow queries with filters to reduce response size
- Verify with reliable endpoints: Use
/tickets.jsonor/users.jsonto test tokens (not/users/me.json) - Status values: open, pending, hold, solved, closed
- Priority values: low, normal, high, urgent
- User roles: end-user, agent, admin (need agent or admin role for API access)
- Ticket types: problem, incident, question, task
- Authentication format: email/token:api_token (curl -u handles encoding)
- New workspaces: Fresh Zendesk accounts come with sample tickets for testing
API Reference
- Main Documentation: https://developer.zendesk.com/api-reference/
- Tickets API: https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/
- Users API: https://developer.zendesk.com/api-reference/ticketing/users/users/
- Organizations API: https://developer.zendesk.com/api-reference/ticketing/organizations/organizations/
- Groups API: https://developer.zendesk.com/api-reference/ticketing/groups/groups/
- Search API: https://developer.zendesk.com/documentation/ticketing/using-the-zendesk-api/searching-with-the-zendesk-api/
- Rate Limits: https://developer.zendesk.com/api-reference/introduction/rate-limits/
- Authentication: https://developer.zendesk.com/api-reference/introduction/security-and-auth/
- Admin Center: https://www.zendesk.com/admin/