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 Setup API Wrapper Create a helper script for API calls: cat
/tmp/zendesk-curl << 'EOF'
!/bin/bash
- curl -s -H "Content-Type: application/json" -H "Authorization: Bearer $ZENDESK_API_TOKEN" "$@"
- EOF
- chmod
- +x /tmp/zendesk-curl
- Usage:
- All examples below use
- /tmp/zendesk-curl
- instead of direct
- curl
- calls.
- 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:
- /tmp/zendesk-curl
- "https://
- ${ZENDESK_SUBDOMAIN}
- .zendesk.com/api/v2/tickets.json"
- |
- jq '
- {
- count: .count, tickets: .tickets
- |
- length
- }
- Expected response: Ticket count and list
- Alternative verification (list users):
- /tmp/zendesk-curl
- "https://
- ${ZENDESK_SUBDOMAIN}
- .zendesk.com/api/v2/users.json"
- |
- 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.
- 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): /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets.json" | jq '.tickets [ ] | { id, subject, status, priority } With pagination: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets.json?page=1&per_page=50" 2. Get Ticket Retrieve a specific ticket: TICKET_ID = "123" /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} .json" 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: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets.json" -d @/tmp/zendesk_request.json 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: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets.json" -d @/tmp/zendesk_request.json 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: /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} .json" -d @/tmp/zendesk_request.json 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 /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} .json" -d @/tmp/zendesk_request.json 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: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/create_many.json" -d @/tmp/zendesk_request.json 7. List Users Get all users: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users.json" | jq '.users [ ] | { id, name, email, role } 8. Get Current User Get authenticated user details: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users/me.json" 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: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users.json" -d @/tmp/zendesk_request.json Create an agent: Write to /tmp/zendesk_request.json : { "user" : { "name" : "Jane Agent" , "email" : "jane@company.com" , "role" : "agent" } } Then run: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users.json" -d @/tmp/zendesk_request.json 10. Update User Update user information: USER_ID = "456" Write to /tmp/zendesk_request.json : { "user" : { "name" : "Updated Name" , "phone" : "+1234567890" } } Then run: /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users/ ${USER_ID} .json" -d @/tmp/zendesk_request.json 11. Search Users Search for users by query: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/users/search.json?query=john" | jq '.users [ ] | { id, name, email } 12. List Organizations Get all organizations: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/organizations.json" | 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: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/organizations.json" -d @/tmp/zendesk_request.json 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: /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/organizations/ ${ORG_ID} .json" -d @/tmp/zendesk_request.json 15. List Groups Get all agent groups: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/groups.json" | jq '.groups [ ] | { id, name } 16. Create Group Create a new agent group: Write to /tmp/zendesk_request.json : { "group" : { "name" : "Support Team" } } Then run: /tmp/zendesk-curl -X POST "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/groups.json" -d @/tmp/zendesk_request.json 17. Search API Search for open tickets: Write to /tmp/zendesk_query.txt : type:ticket status:open /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/search.json" | jq '.results [ ] | { id, subject, status } Search for high priority tickets: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/search.json" | jq '.results [ ] Search tickets with keywords: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/search.json" | jq '.results [ ] Search users by email domain: /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/search.json" | jq '.results [ ] 18. Get Ticket Comments List all comments on a ticket: TICKET_ID = "123" /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} /comments.json" | 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 /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} .json" -d @/tmp/zendesk_request.json 20. Bulk Update Tickets Update multiple tickets at once: Write to /tmp/zendesk_request.json : { "ticket" : { "status" : "solved" } } Then run: /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/update_many.json?ids=123,124,125" -d @/tmp/zendesk_request.json 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 /tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/ ${TICKET_ID} .json" -d @/tmp/zendesk_request.json Find and Close Old Tickets
Search for old open tickets (30+ days)
OLD_TICKETS
" $( /tmp/zendesk-curl "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/search.json" | jq -r '.results[].id' | paste -sd "," - ) " Write to /tmp/zendesk_request.json : { "ticket" : { "status" : "closed" } } Then run:
Bulk close them
/tmp/zendesk-curl -X PUT "https:// ${ZENDESK_SUBDOMAIN} .zendesk.com/api/v2/tickets/update_many.json?ids= ${OLD_TICKETS} " -d @/tmp/zendesk_request.json Search Query Syntax Ticket Search Operators type:ticket - Search tickets only status:open - Filter by status (open, pending, solved, closed) priority:high - Filter by priority (low, normal, high, urgent) assignee:name - Find tickets assigned to specific agent group:name - Find tickets in specific group tags:keyword - Search by tag created>2024-01-01 - Created after date created<30 - Created in last 30 days "exact phrase" - Search exact text User Search Operators type:user - Search users only role:agent - Filter by role (end-user, agent, admin) email:*@domain.com - Search by email domain name: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-Remaining
- header
- Use bulk operations
- :
- create_many
- ,
- update_many
- endpoints save API calls
- Implement exponential backoff
-
- Honor
- Retry-After
- header 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.json
- or
- /users.json
- to 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/