Tickets

Warning

Ticket endpoints depend on group permissions and if the user you’re using is an agent. Because of this tickets may or may not be available.

Tip

Suppress notifications

To create or update a ticket without triggering agent notifications (email and in-app), add the following HTTP header to your request:

X-Zammad-Suppress-Notifications: true

This is useful for automated integrations that manage tickets via webhooks or triggers to avoid notification loops. The header only affects admin and agent accounts and is ignored for customers.

List

Required permission: ticket.agent or ticket.customer

GET-Request sent: /api/v1/tickets

Response:

# HTTP-Code 200 Ok

[
   {
      "id": 1,
      "group_id": 1,
      "priority_id": 2,
      "state_id": 1,
      "organization_id": 1,
      "number": "22001",
      "title": "Welcome to Zammad!",
      "owner_id": 1,
      "customer_id": 2,
      "note": null,
      "first_response_at": null,
      "first_response_escalation_at": null,
      "first_response_in_min": null,
      "first_response_diff_in_min": null,
      "close_at": null,
      "close_escalation_at": null,
      "close_in_min": null,
      "close_diff_in_min": null,
      "update_escalation_at": null,
      "update_in_min": null,
      "update_diff_in_min": null,
      "last_contact_at": "2021-11-03T11:51:13.790Z",
      "last_contact_agent_at": null,
      "last_contact_customer_at": "2021-11-03T11:51:13.790Z",
      "last_owner_update_at": null,
      "create_article_type_id": 5,
      "create_article_sender_id": 2,
      "article_count": 1,
      "escalation_at": null,
      "pending_time": null,
      "type": null,
      "time_unit": null,
      "preferences": {},
      "updated_by_id": 2,
      "created_by_id": 2,
      "created_at": "2021-11-03T11:51:13.759Z",
      "updated_at": "2021-11-03T11:51:13.809Z"
   },
   {
      "id": 2,
      "group_id": 1,
      "priority_id": 2,
      "state_id": 4,
      "organization_id": 3,
      "number": "22002",
      "title": "Order 777555",
      "owner_id": 3,
      "customer_id": 6,
      "note": null,
      "first_response_at": null,
      "first_response_escalation_at": null,
      "first_response_in_min": null,
      "first_response_diff_in_min": null,
      "close_at": null,
      "close_escalation_at": null,
      "close_in_min": null,
      "close_diff_in_min": null,
      "update_escalation_at": null,
      "update_in_min": null,
      "update_diff_in_min": null,
      "last_contact_at": "2021-05-04T16:57:17.920Z",
      "last_contact_agent_at": "2021-05-03T10:57:17.904Z",
      "last_contact_customer_at": "2021-05-04T16:57:17.920Z",
      "last_owner_update_at": null,
      "create_article_type_id": 1,
      "create_article_sender_id": 2,
      "article_count": 3,
      "escalation_at": null,
      "pending_time": null,
      "type": null,
      "time_unit": null,
      "preferences": {},
      "updated_by_id": 6,
      "created_by_id": 6,
      "created_at": "2021-05-03T09:57:17.837Z",
      "updated_at": "2021-11-03T11:57:17.927Z"
   },

   ...
]

Show

Required permission: ticket.agent or ticket.customer

GET-Request sent: /api/v1/tickets/{ticket id}

Response:

# HTTP-Code 200 Ok

{
   "id": 3,
   "group_id": 1,
   "priority_id": 2,
   "state_id": 4,
   "organization_id": 3,
   "number": "22003",
   "title": "Order 787556",
   "owner_id": 3,
   "customer_id": 7,
   "note": null,
   "first_response_at": null,
   "first_response_escalation_at": null,
   "first_response_in_min": null,
   "first_response_diff_in_min": null,
   "close_at": null,
   "close_escalation_at": null,
   "close_in_min": null,
   "close_diff_in_min": null,
   "update_escalation_at": null,
   "update_in_min": null,
   "update_diff_in_min": null,
   "last_contact_at": "2021-06-03T09:57:17.987Z",
   "last_contact_agent_at": "2021-06-03T09:57:17.987Z",
   "last_contact_customer_at": "2021-06-01T11:57:17.935Z",
   "last_owner_update_at": null,
   "create_article_type_id": 1,
   "create_article_sender_id": 2,
   "article_count": 2,
   "escalation_at": null,
   "pending_time": null,
   "type": null,
   "time_unit": null,
   "preferences": {},
   "updated_by_id": 4,
   "created_by_id": 7,
   "created_at": "2021-06-01T11:57:17.935Z",
   "updated_at": "2021-11-03T11:57:17.997Z"
}

Create

Required permission: ticket.agent or ticket.customer

Tip

On behalf of users

If you want to create tickets on behalf of other users, use the customer_id attribute. This requires the ticket.agent permission. Without it, customer_id is ignored and the ticket’s Customer field is set to the current user. Use guess:{email address} to save an API call if you don’t know the user’s ID or want to create the user in question ("customer_id": "guess:jane@doe.com").

When creating a ticket on behalf of a customer with an initial article, you must set article.sender to “Customer” explicitly. Without this, the sender defaults to “Agent” (based on the current user’s permission). This affects the ticket’s create_article_sender_id and the resulting contact timestamp calculations.

The same applies to articles added later via PUT: set sender explicitly there as well when acting on behalf of a customer. Since the sender of an article cannot be changed after creation, it is important to set it correctly from the start.

For more details on the sender attribute, see Articles.

Tip

Add mention subscription right away

Add the mentions attribute to your ticket payload and provide an array of user ids to directly subscribe them during ticket creation.

E.g.: "mentions": [1, 5, 7, 8],

POST-Request sent: /api/v1/tickets

{
   "title": "Help me!",
   "group": "2nd Level",
   "customer": "david@example.com",
   "article": {
      "subject": "My subject",
      "body": "I am a message!",
      "type": "note",
      "sender": "Customer",
      "internal": false
   }
}

Response:

# HTTP-Code 201 Created

{
   "id": 19,
   "group_id": 2,
   "priority_id": 2,
   "state_id": 1,
   "organization_id": null,
   "number": "22019",
   "title": "Help me!",
   "owner_id": 1,
   "customer_id": 10,
   "note": null,
   "first_response_at": null,
   "first_response_escalation_at": null,
   "first_response_in_min": null,
   "first_response_diff_in_min": null,
   "close_at": null,
   "close_escalation_at": null,
   "close_in_min": null,
   "close_diff_in_min": null,
   "update_escalation_at": null,
   "update_in_min": null,
   "update_diff_in_min": null,
   "last_contact_at": null,
   "last_contact_agent_at": null,
   "last_contact_customer_at": null,
   "last_owner_update_at": null,
   "create_article_type_id": 10,
   "create_article_sender_id": 2,
   "article_count": 1,
   "escalation_at": null,
   "pending_time": null,
   "type": null,
   "time_unit": null,
   "preferences": {},
   "updated_by_id": 3,
   "created_by_id": 3,
   "created_at": "2021-11-08T14:17:41.913Z",
   "updated_at": "2021-11-08T14:17:41.994Z",
   "article_ids": [
      30
   ],
   "ticket_time_accounting_ids": []
}

Hint

The sender attribute of the initial article determines the ticket’s create_article_sender_id and contact timestamps. For the full list of article attributes and their behavior, see Articles.

Update

Required permission: ticket.agent or ticket.customer

PUT-Request sent: /api/v1/tickets/{ticket id}

{
   "title": "No help for you",
   "group": "Sales",
   "state": "open",
   "priority": "3 high",
   "article": {
      "subject": "Update via API",
      "body": "Here's my reason for updating this ticket...",
      "internal": true
   }
}

Note

Above example provides an article. This article is a new article and does not affect any existing ones.

Response:

# HTTP-Code 200 Ok

{
   "id": 19,
   "group_id": 1,
   "priority_id": 3,
   "state_id": 2,
   "organization_id": null,
   "number": "22019",
   "title": "No help for you",
   "owner_id": 1,
   "customer_id": 10,
   "note": null,
   "first_response_at": null,
   "first_response_escalation_at": null,
   "first_response_in_min": null,
   "first_response_diff_in_min": null,
   "close_at": null,
   "close_escalation_at": null,
   "close_in_min": null,
   "close_diff_in_min": null,
   "update_escalation_at": null,
   "update_in_min": null,
   "update_diff_in_min": null,
   "last_contact_at": null,
   "last_contact_agent_at": null,
   "last_contact_customer_at": null,
   "last_owner_update_at": null,
   "create_article_type_id": 10,
   "create_article_sender_id": 1,
   "article_count": 2,
   "escalation_at": null,
   "pending_time": null,
   "type": null,
   "time_unit": null,
   "preferences": {},
   "updated_by_id": 3,
   "created_by_id": 3,
   "created_at": "2021-11-08T14:17:41.913Z",
   "updated_at": "2021-11-08T14:18:53.426Z",
   "article_ids": [
      31,
      30
   ],
   "ticket_time_accounting_ids": []
}

Tip

Adding attachments

Attachment payloads are identical to the POST method, just use PUT instead.

Delete

Required permission: admin

Danger

⚠ This is a permanent removal

Please note that removing tickets cannot be undone. All data (e.g.: articles & attachments) will be lost.

DELETE-Request sent: /api/v1/tickets/{ticket id}

Response:

# HTTP-Code 200 Ok
{}