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.
/plugin marketplace add vm0-ai/api0/plugin install api0@api0This skill inherits all available tools. When active, it can use any tool Claude has access to.
Manage customer support tickets, users, organizations, and support operations via the Zendesk Support REST API.
Official docs:
https://developer.zendesk.com/api-reference/
Use this skill when you need to:
⚠️ Important: You must enable Token Access before creating tokens.
export ZENDESK_EMAIL="your-email@company.com"
export ZENDESK_API_TOKEN="your_api_token"
export ZENDESK_SUBDOMAIN="yourcompany"
Your subdomain is in your Zendesk URL:
https://yourcompany.zendesk.com
^^^^^^^^^^^
subdomain
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 .
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.
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 .
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 .
Create a new support ticket:
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 '"'"'{"ticket": {"subject": "My printer is on fire!", "comment": {"body": "The smoke is very colorful."}, "priority": "urgent"}}'"'"'' | jq .
Create ticket with more details:
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 '"'"'{"ticket": {"subject": "Need help with account", "comment": {"body": "I cannot access my account settings."}, "priority": "high", "status": "open", "type": "problem", "tags": ["account", "access"]}}'"'"'' | jq .
Update an existing ticket:
TICKET_ID="123"
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 '"'"'{"ticket": {"status": "solved", "comment": {"body": "Issue has been resolved. Thank you!", "public": true}}}'"'"'' | jq .
Change priority and assignee:
TICKET_ID="123"
ASSIGNEE_ID="456"
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 "{\"ticket\": {\"priority\": \"high\", \"assignee_id\": ${ASSIGNEE_ID}}}"' | jq .
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}"
Bulk create tickets:
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 '"'"'{"tickets": [{"subject": "Ticket 1", "comment": {"body": "First ticket"}}, {"subject": "Ticket 2", "comment": {"body": "Second ticket"}}]}'"'"'' | jq .
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}
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 .
Create an end-user:
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 '"'"'{"user": {"name": "John Customer", "email": "john@example.com", "role": "end-user"}}'"'"'' | jq .
Create an agent:
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 '"'"'{"user": {"name": "Jane Agent", "email": "jane@company.com", "role": "agent"}}'"'"'' | jq .
Update user information:
USER_ID="456"
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 '"'"'{"user": {"name": "Updated Name", "phone": "+1234567890"}}'"'"'' | jq .
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}
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}
Create a new organization:
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 '"'"'{"organization": {"name": "Acme Inc", "domain_names": ["acme.com", "acmeinc.com"], "details": "Important customer"}}'"'"'' | jq .
Update organization details:
ORG_ID="789"
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 '"'"'{"organization": {"name": "Acme Corporation", "notes": "Premium customer since 2020"}}'"'"'' | jq .
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}
Create a new agent group:
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 '"'"'{"group": {"name": "Support Team"}}'"'"'' | jq .
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[]
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}
Assign a ticket to a group:
TICKET_ID="123"
GROUP_ID="456"
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 "{\"ticket\": {\"group_id\": ${GROUP_ID}}}"' | jq .
Update multiple tickets at once:
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 '"'"'{"ticket": {"status": "solved"}}'"'"'' | jq .
# 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 '{"ticket": {"subject": "New issue", "comment": {"body": "Need help"}}}')
TICKET_ID=$(echo $TICKET_RESPONSE | jq -r '.ticket.id')
# Assign to agent
ASSIGNEE_ID="789"
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 "{\"ticket\": {\"assignee_id\": ${ASSIGNEE_ID}, \"status\": \"open\"}}"
# 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 "," -)"
# 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 '{"ticket": {"status": "closed"}}'
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 texttype:user - Search users onlyrole:agent - Filter by role (end-user, agent, admin)email:*@domain.com - Search by email domainname:john - Search by nameUse spaces for AND logic:
query=type:ticket status:open priority:high
| Plan | Requests/Minute |
|---|---|
| Team | 200 |
| Growth | 400 |
| Professional | 400 |
| Enterprise | 700 |
| Enterprise Plus | 2,500 |
Special Limits:
X-Rate-Limit: 700 # Your account's limit
X-Rate-Limit-Remaining: 685 # Requests remaining
Retry-After: 45 # Seconds to wait if exceeded
# 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
X-Rate-Limit-Remaining headercreate_many, update_many endpoints save API callsRetry-After header on 429 responses/tickets.json or /users.json to test tokens (not /users/me.json)