python-zendesk-sdk 0.4.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/PKG-INFO +58 -10
  2. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/README.md +57 -9
  3. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/basic_usage.py +24 -0
  4. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/enriched_tickets.py +24 -2
  5. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/pyproject.toml +1 -1
  6. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/__init__.py +11 -1
  7. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/client.py +26 -0
  8. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/__init__.py +2 -0
  9. python_zendesk_sdk-0.6.0/src/zendesk_sdk/clients/ticket_fields.py +101 -0
  10. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/tickets.py +300 -26
  11. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/__init__.py +12 -0
  12. python_zendesk_sdk-0.6.0/src/zendesk_sdk/models/enriched_ticket.py +142 -0
  13. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/search.py +18 -0
  14. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/pagination.py +120 -6
  15. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_clients.py +297 -0
  16. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_models.py +127 -0
  17. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_package_import.py +1 -1
  18. python_zendesk_sdk-0.4.0/src/zendesk_sdk/models/enriched_ticket.py +0 -63
  19. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/.flake8 +0 -0
  20. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/.github/workflows/publish.yml +0 -0
  21. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/.gitignore +0 -0
  22. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/.python-version +0 -0
  23. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/LICENSE +0 -0
  24. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/caching.py +0 -0
  25. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/error_handling.py +0 -0
  26. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/help_center.py +0 -0
  27. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/pagination_example.py +0 -0
  28. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/examples/search.py +0 -0
  29. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/attachments.py +0 -0
  30. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/base.py +0 -0
  31. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/help_center/__init__.py +0 -0
  32. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/help_center/articles.py +0 -0
  33. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/help_center/categories.py +0 -0
  34. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/help_center/sections.py +0 -0
  35. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/organizations.py +0 -0
  36. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/search.py +0 -0
  37. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/clients/users.py +0 -0
  38. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/config.py +0 -0
  39. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/exceptions.py +0 -0
  40. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/http_client.py +0 -0
  41. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/base.py +0 -0
  42. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/comment.py +0 -0
  43. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/help_center.py +0 -0
  44. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/organization.py +0 -0
  45. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/ticket.py +0 -0
  46. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/src/zendesk_sdk/models/user.py +0 -0
  47. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/__init__.py +0 -0
  48. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_client.py +0 -0
  49. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_config.py +0 -0
  50. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_exceptions.py +0 -0
  51. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_help_center_client.py +0 -0
  52. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_http_client.py +0 -0
  53. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_pagination.py +0 -0
  54. {python_zendesk_sdk-0.4.0 → python_zendesk_sdk-0.6.0}/tests/test_search_query_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-zendesk-sdk
3
- Version: 0.4.0
3
+ Version: 0.6.0
4
4
  Summary: Modern Python SDK for Zendesk API
5
5
  Project-URL: Homepage, https://github.com/bormog/python-zendesk-sdk
6
6
  Project-URL: Repository, https://github.com/bormog/python-zendesk-sdk
@@ -36,15 +36,15 @@ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
36
36
  Requires-Dist: pytest>=7.0.0; extra == 'dev'
37
37
  Description-Content-Type: text/markdown
38
38
 
39
- # Python Zendesk SDK
39
+ ![header](https://capsule-render.vercel.app/api?type=waving&color=0:ff4400,100:ff00ff&height=200&section=header&text=python-zendesk-sdk&fontSize=50&fontColor=ffffff&fontAlignY=35&desc=Modern%20async%20SDK%20for%20Zendesk%20API&descSize=18&descAlignY=55&animation=fadeIn)
40
40
 
41
- [![PyPI](https://img.shields.io/pypi/v/python-zendesk-sdk)](https://pypi.org/project/python-zendesk-sdk/)
42
- [![Python](https://img.shields.io/pypi/pyversions/python-zendesk-sdk)](https://pypi.org/project/python-zendesk-sdk/)
43
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/python-zendesk-sdk?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/python-zendesk-sdk)
44
- [![License](https://img.shields.io/github/license/bormog/python-zendesk-sdk)](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
45
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
46
- [![Pydantic v2](https://img.shields.io/badge/Pydantic-v2-blue)](https://docs.pydantic.dev/)
47
- [![Async](https://img.shields.io/badge/async-first-blueviolet)](https://docs.python.org/3/library/asyncio.html)
41
+ [![PyPI](https://img.shields.io/pypi/v/python-zendesk-sdk?color=ff00ff&logo=pypi&logoColor=white)](https://pypi.org/project/python-zendesk-sdk/)
42
+ [![Python](https://img.shields.io/pypi/pyversions/python-zendesk-sdk?color=ff4400&logo=python&logoColor=white)](https://pypi.org/project/python-zendesk-sdk/)
43
+ [![Downloads](https://img.shields.io/pepy/dt/python-zendesk-sdk?color=ff00ff&logo=downloads&logoColor=white)](https://pepy.tech/projects/python-zendesk-sdk)
44
+ [![License](https://img.shields.io/github/license/bormog/python-zendesk-sdk?color=ff4400&logo=opensourceinitiative&logoColor=white)](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
45
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000?logo=python&logoColor=white)](https://github.com/psf/black)
46
+ [![Pydantic v2](https://img.shields.io/badge/Pydantic-v2-ff00ff?logo=pydantic&logoColor=white)](https://docs.pydantic.dev/)
47
+ [![Async](https://img.shields.io/badge/async-first-ff4400?logo=python&logoColor=white)](https://docs.python.org/3/library/asyncio.html)
48
48
 
49
49
  Modern Python SDK for Zendesk API, designed for automation and AI agents.
50
50
 
@@ -61,6 +61,7 @@ Modern Python SDK for Zendesk API, designed for automation and AI agents.
61
61
  - [Tickets](#tickets)
62
62
  - [Comments](#comments-nested-under-tickets)
63
63
  - [Tags](#tags-nested-under-tickets)
64
+ - [Ticket Fields](#ticket-fields)
64
65
  - [Enriched Tickets](#enriched-tickets)
65
66
  - [Attachments](#attachments)
66
67
  - [Search](#search)
@@ -194,10 +195,32 @@ paginator = client.organizations.list() # List organizations (paginator
194
195
 
195
196
  ### Tickets
196
197
  ```python
198
+ # Read
197
199
  ticket = await client.tickets.get(ticket_id) # Get ticket by ID
198
200
  paginator = client.tickets.list() # List tickets (paginator)
199
201
  paginator = client.tickets.for_user(user_id) # User's tickets (paginator)
200
202
  paginator = client.tickets.for_organization(org_id) # Org's tickets (paginator)
203
+
204
+ # Create
205
+ ticket = await client.tickets.create(
206
+ comment_body="Customer needs help with login",
207
+ subject="Login Issue",
208
+ priority="high", # low, normal, high, urgent
209
+ status="open", # new, open, pending, hold, solved
210
+ ticket_type="problem", # question, incident, problem, task
211
+ tags=["login", "urgent"],
212
+ )
213
+
214
+ # Update
215
+ ticket = await client.tickets.update(
216
+ ticket_id,
217
+ status="solved",
218
+ priority="normal",
219
+ comment={"body": "Issue resolved!", "public": True},
220
+ )
221
+
222
+ # Delete (moves to trash, recoverable for 30 days)
223
+ await client.tickets.delete(ticket_id)
201
224
  ```
202
225
 
203
226
  ### Comments (nested under tickets)
@@ -216,9 +239,22 @@ tags = await client.tickets.tags.set(ticket_id, ["new"]) # Replace all tags
216
239
  tags = await client.tickets.tags.remove(ticket_id, ["old"]) # Remove tags
217
240
  ```
218
241
 
242
+ ### Ticket Fields
243
+ ```python
244
+ # Get all ticket fields (system + custom)
245
+ async for field in client.ticket_fields.list():
246
+ print(f"{field.title}: {field.type}")
247
+
248
+ # Get specific field by ID (cached)
249
+ field = await client.ticket_fields.get(field_id)
250
+
251
+ # Find field by title (case-insensitive)
252
+ field = await client.ticket_fields.get_by_title("Subscription")
253
+ ```
254
+
219
255
  ### Enriched Tickets
220
256
 
221
- Load tickets with all related data (comments + users) in minimum API requests:
257
+ Load tickets with all related data (comments, users, field definitions) in minimum API requests:
222
258
 
223
259
  ```python
224
260
  from zendesk_sdk import SearchQueryConfig
@@ -234,6 +270,13 @@ for comment in enriched.comments:
234
270
  author = enriched.get_comment_author(comment)
235
271
  print(f"Comment by {author.name}: {comment.body[:50]}...")
236
272
 
273
+ # Access custom field values with human-readable names
274
+ field_values = enriched.get_field_values()
275
+ print(f"Subscription: {field_values.get('Subscription')}")
276
+
277
+ # Or get specific field value by ID
278
+ value = enriched.get_field_value(360001234)
279
+
237
280
  # Search with all data loaded (using SearchQueryConfig)
238
281
  config = SearchQueryConfig.tickets(
239
282
  status=["open"],
@@ -455,6 +498,7 @@ The SDK provides specific exception classes for different error types:
455
498
  from zendesk_sdk.exceptions import (
456
499
  ZendeskAuthException,
457
500
  ZendeskHTTPException,
501
+ ZendeskPaginationException,
458
502
  ZendeskRateLimitException,
459
503
  ZendeskTimeoutException,
460
504
  ZendeskValidationException,
@@ -475,6 +519,9 @@ async with ZendeskClient(config) as client:
475
519
  except ZendeskTimeoutException as e:
476
520
  # Request timeout
477
521
  print(f"Timeout: {e.message}")
522
+ except ZendeskPaginationException as e:
523
+ # Pagination errors (e.g., Zendesk 1000 result limit)
524
+ print(f"Pagination error: {e.message}")
478
525
  ```
479
526
 
480
527
  ### Automatic Retry
@@ -505,6 +552,7 @@ The SDK includes built-in caching for frequently accessed resources. Caching is
505
552
  |----------|-----|----------|
506
553
  | Users | 5 min | 1000 |
507
554
  | Organizations | 10 min | 500 |
555
+ | Ticket Fields | 30 min | 200 |
508
556
  | Articles | 15 min | 500 |
509
557
  | Categories | 30 min | 200 |
510
558
  | Sections | 30 min | 200 |
@@ -1,12 +1,12 @@
1
- # Python Zendesk SDK
1
+ ![header](https://capsule-render.vercel.app/api?type=waving&color=0:ff4400,100:ff00ff&height=200&section=header&text=python-zendesk-sdk&fontSize=50&fontColor=ffffff&fontAlignY=35&desc=Modern%20async%20SDK%20for%20Zendesk%20API&descSize=18&descAlignY=55&animation=fadeIn)
2
2
 
3
- [![PyPI](https://img.shields.io/pypi/v/python-zendesk-sdk)](https://pypi.org/project/python-zendesk-sdk/)
4
- [![Python](https://img.shields.io/pypi/pyversions/python-zendesk-sdk)](https://pypi.org/project/python-zendesk-sdk/)
5
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/python-zendesk-sdk?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/python-zendesk-sdk)
6
- [![License](https://img.shields.io/github/license/bormog/python-zendesk-sdk)](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
7
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
8
- [![Pydantic v2](https://img.shields.io/badge/Pydantic-v2-blue)](https://docs.pydantic.dev/)
9
- [![Async](https://img.shields.io/badge/async-first-blueviolet)](https://docs.python.org/3/library/asyncio.html)
3
+ [![PyPI](https://img.shields.io/pypi/v/python-zendesk-sdk?color=ff00ff&logo=pypi&logoColor=white)](https://pypi.org/project/python-zendesk-sdk/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/python-zendesk-sdk?color=ff4400&logo=python&logoColor=white)](https://pypi.org/project/python-zendesk-sdk/)
5
+ [![Downloads](https://img.shields.io/pepy/dt/python-zendesk-sdk?color=ff00ff&logo=downloads&logoColor=white)](https://pepy.tech/projects/python-zendesk-sdk)
6
+ [![License](https://img.shields.io/github/license/bormog/python-zendesk-sdk?color=ff4400&logo=opensourceinitiative&logoColor=white)](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
7
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000?logo=python&logoColor=white)](https://github.com/psf/black)
8
+ [![Pydantic v2](https://img.shields.io/badge/Pydantic-v2-ff00ff?logo=pydantic&logoColor=white)](https://docs.pydantic.dev/)
9
+ [![Async](https://img.shields.io/badge/async-first-ff4400?logo=python&logoColor=white)](https://docs.python.org/3/library/asyncio.html)
10
10
 
11
11
  Modern Python SDK for Zendesk API, designed for automation and AI agents.
12
12
 
@@ -23,6 +23,7 @@ Modern Python SDK for Zendesk API, designed for automation and AI agents.
23
23
  - [Tickets](#tickets)
24
24
  - [Comments](#comments-nested-under-tickets)
25
25
  - [Tags](#tags-nested-under-tickets)
26
+ - [Ticket Fields](#ticket-fields)
26
27
  - [Enriched Tickets](#enriched-tickets)
27
28
  - [Attachments](#attachments)
28
29
  - [Search](#search)
@@ -156,10 +157,32 @@ paginator = client.organizations.list() # List organizations (paginator
156
157
 
157
158
  ### Tickets
158
159
  ```python
160
+ # Read
159
161
  ticket = await client.tickets.get(ticket_id) # Get ticket by ID
160
162
  paginator = client.tickets.list() # List tickets (paginator)
161
163
  paginator = client.tickets.for_user(user_id) # User's tickets (paginator)
162
164
  paginator = client.tickets.for_organization(org_id) # Org's tickets (paginator)
165
+
166
+ # Create
167
+ ticket = await client.tickets.create(
168
+ comment_body="Customer needs help with login",
169
+ subject="Login Issue",
170
+ priority="high", # low, normal, high, urgent
171
+ status="open", # new, open, pending, hold, solved
172
+ ticket_type="problem", # question, incident, problem, task
173
+ tags=["login", "urgent"],
174
+ )
175
+
176
+ # Update
177
+ ticket = await client.tickets.update(
178
+ ticket_id,
179
+ status="solved",
180
+ priority="normal",
181
+ comment={"body": "Issue resolved!", "public": True},
182
+ )
183
+
184
+ # Delete (moves to trash, recoverable for 30 days)
185
+ await client.tickets.delete(ticket_id)
163
186
  ```
164
187
 
165
188
  ### Comments (nested under tickets)
@@ -178,9 +201,22 @@ tags = await client.tickets.tags.set(ticket_id, ["new"]) # Replace all tags
178
201
  tags = await client.tickets.tags.remove(ticket_id, ["old"]) # Remove tags
179
202
  ```
180
203
 
204
+ ### Ticket Fields
205
+ ```python
206
+ # Get all ticket fields (system + custom)
207
+ async for field in client.ticket_fields.list():
208
+ print(f"{field.title}: {field.type}")
209
+
210
+ # Get specific field by ID (cached)
211
+ field = await client.ticket_fields.get(field_id)
212
+
213
+ # Find field by title (case-insensitive)
214
+ field = await client.ticket_fields.get_by_title("Subscription")
215
+ ```
216
+
181
217
  ### Enriched Tickets
182
218
 
183
- Load tickets with all related data (comments + users) in minimum API requests:
219
+ Load tickets with all related data (comments, users, field definitions) in minimum API requests:
184
220
 
185
221
  ```python
186
222
  from zendesk_sdk import SearchQueryConfig
@@ -196,6 +232,13 @@ for comment in enriched.comments:
196
232
  author = enriched.get_comment_author(comment)
197
233
  print(f"Comment by {author.name}: {comment.body[:50]}...")
198
234
 
235
+ # Access custom field values with human-readable names
236
+ field_values = enriched.get_field_values()
237
+ print(f"Subscription: {field_values.get('Subscription')}")
238
+
239
+ # Or get specific field value by ID
240
+ value = enriched.get_field_value(360001234)
241
+
199
242
  # Search with all data loaded (using SearchQueryConfig)
200
243
  config = SearchQueryConfig.tickets(
201
244
  status=["open"],
@@ -417,6 +460,7 @@ The SDK provides specific exception classes for different error types:
417
460
  from zendesk_sdk.exceptions import (
418
461
  ZendeskAuthException,
419
462
  ZendeskHTTPException,
463
+ ZendeskPaginationException,
420
464
  ZendeskRateLimitException,
421
465
  ZendeskTimeoutException,
422
466
  ZendeskValidationException,
@@ -437,6 +481,9 @@ async with ZendeskClient(config) as client:
437
481
  except ZendeskTimeoutException as e:
438
482
  # Request timeout
439
483
  print(f"Timeout: {e.message}")
484
+ except ZendeskPaginationException as e:
485
+ # Pagination errors (e.g., Zendesk 1000 result limit)
486
+ print(f"Pagination error: {e.message}")
440
487
  ```
441
488
 
442
489
  ### Automatic Retry
@@ -467,6 +514,7 @@ The SDK includes built-in caching for frequently accessed resources. Caching is
467
514
  |----------|-----|----------|
468
515
  | Users | 5 min | 1000 |
469
516
  | Organizations | 10 min | 500 |
517
+ | Ticket Fields | 30 min | 200 |
470
518
  | Articles | 15 min | 500 |
471
519
  | Categories | 30 min | 200 |
472
520
  | Sections | 30 min | 200 |
@@ -3,6 +3,7 @@
3
3
  This example demonstrates:
4
4
  - Configuration setup
5
5
  - Basic API operations (get users, tickets, organizations)
6
+ - Ticket CRUD (create, update, delete)
6
7
  - Pagination basics
7
8
  - Search functionality
8
9
  """
@@ -42,6 +43,29 @@ async def main() -> None:
42
43
  ticket = await client.tickets.get(12345)
43
44
  print(f"Ticket: {ticket.subject} (status: {ticket.status})")
44
45
 
46
+ # Create a new ticket
47
+ new_ticket = await client.tickets.create(
48
+ comment_body="Customer cannot access their account",
49
+ subject="Account Access Issue",
50
+ priority="high",
51
+ ticket_type="incident",
52
+ tags=["account", "access"],
53
+ )
54
+ print(f"Created ticket: #{new_ticket.id} - {new_ticket.subject}")
55
+
56
+ # Update the ticket
57
+ updated_ticket = await client.tickets.update(
58
+ new_ticket.id,
59
+ status="open",
60
+ priority="normal",
61
+ comment={"body": "Working on this issue", "public": False},
62
+ )
63
+ print(f"Updated ticket status: {updated_ticket.status}")
64
+
65
+ # Delete the ticket (moves to trash)
66
+ await client.tickets.delete(new_ticket.id)
67
+ print(f"Deleted ticket: #{new_ticket.id}")
68
+
45
69
  # Get ticket comments (returns paginator)
46
70
  comments = await client.tickets.comments.list(12345, limit=10).collect()
47
71
  print(f"Ticket has {len(comments)} comments (limited to 10)")
@@ -1,8 +1,9 @@
1
1
  """Enriched tickets example for Zendesk SDK.
2
2
 
3
3
  This example demonstrates:
4
- - Loading tickets with all related data (comments + users)
4
+ - Loading tickets with all related data (comments, users, field definitions)
5
5
  - Using EnrichedTicket for efficient data access
6
+ - Accessing custom field values with human-readable names
6
7
  - Minimizing API requests with batch loading
7
8
  """
8
9
 
@@ -22,7 +23,8 @@ async def main() -> None:
22
23
  # ==================== Single enriched ticket ====================
23
24
 
24
25
  # Get a single ticket with all related data
25
- # This makes 2 API calls: ticket + comments (with sideloaded users)
26
+ # This makes 2 parallel API calls: ticket (with users) + fields
27
+ # Then fetches comments
26
28
  enriched = await client.tickets.get_enriched(12345)
27
29
 
28
30
  print(f"Ticket: {enriched.ticket.subject}")
@@ -40,6 +42,26 @@ async def main() -> None:
40
42
  else:
41
43
  print("Ticket is unassigned")
42
44
 
45
+ # ==================== Custom field values ====================
46
+
47
+ # Get all custom field values as dict with human-readable names
48
+ field_values = enriched.get_field_values()
49
+ print(f"\nCustom fields ({len(field_values)}):")
50
+ for name, value in field_values.items():
51
+ print(f" {name}: {value}")
52
+
53
+ # Or get specific field value by ID
54
+ subscription = enriched.get_field_value(360001234) # Replace with your field ID
55
+ if subscription:
56
+ print(f"\nSubscription level: {subscription}")
57
+
58
+ # Get field definition for more details
59
+ field = enriched.get_field(360001234)
60
+ if field:
61
+ print(f"Field type: {field.type}, Required: {field.required}")
62
+
63
+ # ==================== Comments with authors ====================
64
+
43
65
  # Process comments with author information
44
66
  print(f"\nComments ({len(enriched.comments)}):")
45
67
  for comment in enriched.comments:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-zendesk-sdk"
3
- version = "0.4.0"
3
+ version = "0.6.0"
4
4
  description = "Modern Python SDK for Zendesk API"
5
5
  authors = [
6
6
  {name = "bormog"}
@@ -5,7 +5,7 @@ This package provides a clean, async-first interface to the Zendesk API
5
5
  with full type safety and comprehensive error handling.
6
6
  """
7
7
 
8
- __version__ = "0.4.0"
8
+ __version__ = "0.6.0"
9
9
 
10
10
  from .client import ZendeskClient
11
11
  from .clients import (
@@ -18,6 +18,7 @@ from .clients import (
18
18
  SearchClient,
19
19
  SectionsClient,
20
20
  TagsClient,
21
+ TicketFieldsClient,
21
22
  TicketsClient,
22
23
  UsersClient,
23
24
  )
@@ -38,9 +39,13 @@ from .models import (
38
39
  Section,
39
40
  SortOrder,
40
41
  TicketChannel,
42
+ TicketField,
41
43
  TicketPriority,
44
+ TicketPriorityInput,
42
45
  TicketStatus,
46
+ TicketStatusInput,
43
47
  TicketType,
48
+ TicketTypeInput,
44
49
  UserRole,
45
50
  )
46
51
 
@@ -53,6 +58,7 @@ __all__ = [
53
58
  "UsersClient",
54
59
  "OrganizationsClient",
55
60
  "TicketsClient",
61
+ "TicketFieldsClient",
56
62
  "CommentsClient",
57
63
  "TagsClient",
58
64
  "AttachmentsClient",
@@ -64,6 +70,7 @@ __all__ = [
64
70
  "ArticlesClient",
65
71
  # Models
66
72
  "EnrichedTicket",
73
+ "TicketField",
67
74
  "Category",
68
75
  "Section",
69
76
  "Article",
@@ -71,8 +78,11 @@ __all__ = [
71
78
  "SearchQueryConfig",
72
79
  "SearchType",
73
80
  "TicketStatus",
81
+ "TicketStatusInput",
74
82
  "TicketPriority",
83
+ "TicketPriorityInput",
75
84
  "TicketType",
85
+ "TicketTypeInput",
76
86
  "TicketChannel",
77
87
  "UserRole",
78
88
  "SortOrder",
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
12
12
  HelpCenterClient,
13
13
  OrganizationsClient,
14
14
  SearchClient,
15
+ TicketFieldsClient,
15
16
  TicketsClient,
16
17
  UsersClient,
17
18
  )
@@ -131,6 +132,31 @@ class ZendeskClient:
131
132
 
132
133
  return TicketsClient(self.http_client)
133
134
 
135
+ @cached_property
136
+ def ticket_fields(self) -> "TicketFieldsClient":
137
+ """Access Ticket Fields API.
138
+
139
+ Provides access to ticket field definitions, including system
140
+ and custom fields. Essential for understanding ticket schema.
141
+
142
+ Example:
143
+ # List all ticket fields
144
+ async for field in client.ticket_fields.list():
145
+ print(f"{field.title}: {field.type}")
146
+
147
+ # Get specific field
148
+ field = await client.ticket_fields.get(12345)
149
+
150
+ # Get only custom fields
151
+ custom = await client.ticket_fields.list_custom()
152
+
153
+ # Get only active fields
154
+ active = await client.ticket_fields.list_active()
155
+ """
156
+ from .clients import TicketFieldsClient
157
+
158
+ return TicketFieldsClient(self.http_client, self.config.cache)
159
+
134
160
  @cached_property
135
161
  def attachments(self) -> "AttachmentsClient":
136
162
  """Access Attachments API.
@@ -4,6 +4,7 @@ from .attachments import AttachmentsClient
4
4
  from .help_center import ArticlesClient, CategoriesClient, HelpCenterClient, SectionsClient
5
5
  from .organizations import OrganizationsClient
6
6
  from .search import SearchClient
7
+ from .ticket_fields import TicketFieldsClient
7
8
  from .tickets import CommentsClient, TagsClient, TicketsClient
8
9
  from .users import UsersClient
9
10
 
@@ -12,6 +13,7 @@ __all__ = [
12
13
  "UsersClient",
13
14
  "OrganizationsClient",
14
15
  "TicketsClient",
16
+ "TicketFieldsClient",
15
17
  "AttachmentsClient",
16
18
  "SearchClient",
17
19
  # Ticket sub-clients
@@ -0,0 +1,101 @@
1
+ """Ticket Fields API client."""
2
+
3
+ from typing import TYPE_CHECKING, Callable, Optional
4
+
5
+ from ..models.ticket import TicketField
6
+ from ..pagination import ZendeskPaginator
7
+ from .base import BaseClient
8
+
9
+ if TYPE_CHECKING:
10
+ from ..config import CacheConfig
11
+ from ..http_client import HTTPClient
12
+ from ..pagination import Paginator
13
+
14
+
15
+ class TicketFieldsClient(BaseClient):
16
+ """Client for Zendesk Ticket Fields API.
17
+
18
+ Provides access to ticket field definitions, including both system
19
+ fields and custom fields. Essential for understanding ticket schema.
20
+
21
+ Example:
22
+ async with ZendeskClient(config) as client:
23
+ # Get all ticket fields
24
+ async for field in client.ticket_fields.list():
25
+ print(f"{field.title}: {field.type}")
26
+
27
+ # Get a specific field by ID
28
+ field = await client.ticket_fields.get(12345)
29
+
30
+ # Find field by title
31
+ field = await client.ticket_fields.get_by_title("Subscription")
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ http_client: "HTTPClient",
37
+ cache_config: Optional["CacheConfig"] = None,
38
+ ) -> None:
39
+ """Initialize TicketFieldsClient with optional caching."""
40
+ super().__init__(http_client, cache_config)
41
+ # Ticket fields change infrequently, use longer TTL (30 minutes)
42
+ if cache_config:
43
+ maxsize = getattr(cache_config, "ticket_field_maxsize", 200)
44
+ ttl = getattr(cache_config, "ticket_field_ttl", 1800)
45
+ else:
46
+ maxsize = 200
47
+ ttl = 1800
48
+ self.get: Callable[[int], TicketField] = self._create_cached_method(
49
+ self._get_impl, maxsize=maxsize, ttl=ttl
50
+ )
51
+
52
+ async def _get_impl(self, field_id: int) -> TicketField:
53
+ """Get a specific ticket field by ID.
54
+
55
+ Results are cached for 30 minutes by default.
56
+
57
+ Args:
58
+ field_id: The ticket field's ID
59
+
60
+ Returns:
61
+ TicketField object
62
+ """
63
+ response = await self._get(f"ticket_fields/{field_id}.json")
64
+ return TicketField(**response["ticket_field"])
65
+
66
+ def list(self, per_page: int = 100, limit: Optional[int] = None) -> "Paginator[TicketField]":
67
+ """Get paginated list of all ticket fields.
68
+
69
+ Returns both system fields and custom fields.
70
+
71
+ Args:
72
+ per_page: Number of fields per page (max 100)
73
+ limit: Maximum number of items to return when iterating (None = no limit)
74
+
75
+ Returns:
76
+ Paginator for iterating through all ticket fields
77
+
78
+ Example:
79
+ # Iterate through all fields
80
+ async for field in client.ticket_fields.list():
81
+ print(f"{field.title} ({field.type})")
82
+
83
+ # Collect to list
84
+ fields = await client.ticket_fields.list().collect()
85
+ """
86
+ return ZendeskPaginator.create_ticket_fields_paginator(self._http, per_page=per_page, limit=limit)
87
+
88
+ async def get_by_title(self, title: str) -> Optional[TicketField]:
89
+ """Find a ticket field by its title.
90
+
91
+ Args:
92
+ title: The title of the ticket field (case-insensitive)
93
+
94
+ Returns:
95
+ TicketField if found, None otherwise
96
+ """
97
+ title_lower = title.lower()
98
+ async for field in self.list():
99
+ if field.title.lower() == title_lower:
100
+ return field
101
+ return None