List tickets

GET/api/v1/tickets

Tickets in the workspace, most recently updated first. Spam, deleted and merged tickets are left out. Filter by status (or the shorthands unresolved and resolved), priority, assignee, team, contact or tag, and search subject and message text with q.

Query parameters

ParameterTypeDescription
statusstringA status value, or unresolved / resolved for every status in that category.
prioritystring
assigneeIdstringOnly tickets assigned to this user. Pass unassigned for tickets with nobody.
teamIdstring
contactIdstring
tagstring
qstringFull-text search over subject, messages and the requester.
limitnumberPage size, 1 to 100. Default 50.
cursorstringThe nextCursor from the previous page.

Example request

curl "https://crowdstack.org/api/v1/tickets?status=unresolved&priority=high" \
  -H "Authorization: Bearer $CROWDSTACK_API_KEY"

Example response

{
  "tickets": [
    {
      "id": "cmf3k2x9a0100abcd",
      "number": 3243,
      "key": "#3243",
      "subject": "Cannot export invoices",
      "status": "open",
      "priority": "high",
      "summary": null,
      "tags": [
        "billing"
      ],
      "fields": {},
      "contact": {
        "id": "cmf3k2x9a0001abcd",
        "firstName": "Jane",
        "lastName": "Doe",
        "email": "jane@acme.com"
      },
      "assignee": {
        "id": "cmf3k2x9a0003abcd",
        "name": "Jane Doe",
        "email": "jane@acme-mail.com"
      },
      "team": null,
      "cc": [],
      "messageCount": 2,
      "sla": {
        "firstReplyDueAt": "2026-09-15T14:12:00.000Z",
        "resolveDueAt": "2026-09-17T10:12:00.000Z",
        "firstReplyBreachedAt": null,
        "resolveBreachedAt": null
      },
      "firstAgentReplyAt": null,
      "resolvedAt": null,
      "statusChangedAt": "2026-09-15T10:12:00.000Z",
      "createdAt": "2026-09-15T10:12:00.000Z",
      "updatedAt": "2026-09-15T10:12:00.000Z"
    }
  ],
  "nextCursor": null
}

Get a ticket

GET/api/v1/tickets/:id

One ticket with its full conversation, oldest message first. Internal notes are included and flagged with isInternal. Look a ticket up by number with list_tickets and q if you only have the number.

Responses

StatusMeaning
404No ticket with that id.

Example request

curl "https://crowdstack.org/api/v1/tickets/cmf3k2x9a0001abcd" \
  -H "Authorization: Bearer $CROWDSTACK_API_KEY"

Example response

{
  "ticket": {
    "id": "cmf3k2x9a0100abcd",
    "number": 3243,
    "key": "#3243",
    "subject": "Cannot export invoices",
    "status": "open",
    "priority": "high",
    "summary": null,
    "tags": [
      "billing"
    ],
    "fields": {},
    "contact": {
      "id": "cmf3k2x9a0001abcd",
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane@acme.com"
    },
    "assignee": {
      "id": "cmf3k2x9a0003abcd",
      "name": "Jane Doe",
      "email": "jane@acme-mail.com"
    },
    "team": null,
    "cc": [],
    "messageCount": 2,
    "sla": {
      "firstReplyDueAt": "2026-09-15T14:12:00.000Z",
      "resolveDueAt": "2026-09-17T10:12:00.000Z",
      "firstReplyBreachedAt": null,
      "resolveBreachedAt": null
    },
    "firstAgentReplyAt": null,
    "resolvedAt": null,
    "statusChangedAt": "2026-09-15T10:12:00.000Z",
    "createdAt": "2026-09-15T10:12:00.000Z",
    "updatedAt": "2026-09-15T10:12:00.000Z",
    "messages": [
      {
        "id": "cmf3k2x9a0110abcd",
        "body": "Hi Jane, thanks for flagging this. Which date range were you exporting?",
        "authorType": "agent",
        "author": {
          "id": "cmf3k2x9a0003abcd",
          "name": "Jane Doe",
          "email": "jane@acme-mail.com"
        },
        "isInternal": false,
        "attachments": [],
        "createdAt": "2026-09-15T10:20:00.000Z"
      }
    ]
  }
}

Create a ticket

POST/api/v1/tickets

Opens a ticket for a customer. Identify them by contactId or by email (a contact is created if needed). By default the body is logged as the customer's message, as if they had written in; set intent to outreach to have the body sent to them as the first agent reply instead.

On-create automations and AI Responses run exactly as they do for a ticket that arrives by email, so an auto-acknowledgement may go out.

The ticket starts in the workspace's default status. Priority defaults to the workspace's default. Tags are free text; get_workspace lists suggestions.

Request body

FieldTypeDescription
subjectrequiredstring
bodyrequiredstringThe first message, plain text.
contactIdstringAn existing contact. Either this or email is required.
emailstringThe customer's email. A contact is created when none exists.
firstNamestringUsed only when a new contact is created.
lastNamestring
intenton_behalf | outreachon_behalf logs the body as the customer's message. outreach sends it to the customer as the first reply. Default "on_behalf".
prioritystring
assigneeIdstring | nullLeave out for an unassigned ticket.
teamIdstring | null
tagsstring[]
fieldsobjectCustom field values keyed by field key. Unknown keys are rejected; get_workspace lists the defined fields.

Responses

StatusMeaning
201Body: { ticket }.
422Neither contactId nor email given, or a value did not validate.

Example request

curl -X POST https://crowdstack.org/api/v1/tickets \
  -H "Authorization: Bearer $CROWDSTACK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@acme.com",
    "firstName": "Jane",
    "subject": "Cannot export invoices",
    "body": "Export button does nothing on the invoices page.",
    "priority": "high",
    "tags": [
      "billing"
    ]
  }'

Example response

{
  "ticket": {
    "id": "cmf3k2x9a0100abcd",
    "number": 3243,
    "key": "#3243",
    "subject": "Cannot export invoices",
    "status": "open",
    "priority": "high",
    "summary": null,
    "tags": [
      "billing"
    ],
    "fields": {},
    "contact": {
      "id": "cmf3k2x9a0001abcd",
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane@acme.com"
    },
    "assignee": {
      "id": "cmf3k2x9a0003abcd",
      "name": "Jane Doe",
      "email": "jane@acme-mail.com"
    },
    "team": null,
    "cc": [],
    "messageCount": 2,
    "sla": {
      "firstReplyDueAt": "2026-09-15T14:12:00.000Z",
      "resolveDueAt": "2026-09-17T10:12:00.000Z",
      "firstReplyBreachedAt": null,
      "resolveBreachedAt": null
    },
    "firstAgentReplyAt": null,
    "resolvedAt": null,
    "statusChangedAt": "2026-09-15T10:12:00.000Z",
    "createdAt": "2026-09-15T10:12:00.000Z",
    "updatedAt": "2026-09-15T10:12:00.000Z"
  }
}

Update a ticket

PATCH/api/v1/tickets/:id

Change status, priority, assignee, team, tags, subject, summary or custom fields. Only keys you send are changed. Status, priority and assignee changes fire the workspace's on-update automations, so a move to Solved can email the customer if an automation says so.

Closed cannot be set by hand; it is applied by automation after a ticket stays Solved. Use the Solved status.

Request body

FieldTypeDescription
subjectstring
statusstringA ticket status by value or label.
prioritystring
assigneeIdstring | nullnull unassigns.
teamIdstring | nullnull removes the team.
tagsstring[]Replaces the tag set.
addTagsstring[]
removeTagsstring[]
summarystring | nullThe agent-written summary shown on the ticket.
fieldsobjectCustom field values keyed by field key. Unknown keys are rejected; get_workspace lists the defined fields.

Responses

StatusMeaning
200Body: { ticket }.
404No ticket with that id.

Example request

curl -X PATCH https://crowdstack.org/api/v1/tickets/cmf3k2x9a0001abcd \
  -H "Authorization: Bearer $CROWDSTACK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "solved",
    "addTags": [
      "resolved-by-agent"
    ]
  }'

Example response

{
  "ticket": {
    "id": "cmf3k2x9a0100abcd",
    "number": 3243,
    "key": "#3243",
    "subject": "Cannot export invoices",
    "status": "solved",
    "priority": "high",
    "summary": null,
    "tags": [
      "billing",
      "resolved-by-agent"
    ],
    "fields": {},
    "contact": {
      "id": "cmf3k2x9a0001abcd",
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane@acme.com"
    },
    "assignee": {
      "id": "cmf3k2x9a0003abcd",
      "name": "Jane Doe",
      "email": "jane@acme-mail.com"
    },
    "team": null,
    "cc": [],
    "messageCount": 2,
    "sla": {
      "firstReplyDueAt": "2026-09-15T14:12:00.000Z",
      "resolveDueAt": "2026-09-17T10:12:00.000Z",
      "firstReplyBreachedAt": null,
      "resolveBreachedAt": null
    },
    "firstAgentReplyAt": null,
    "resolvedAt": null,
    "statusChangedAt": "2026-09-15T10:12:00.000Z",
    "createdAt": "2026-09-15T10:12:00.000Z",
    "updatedAt": "2026-09-15T10:12:00.000Z"
  }
}

Reply to a ticket or add a note

POST/api/v1/tickets/:id/messages

Adds a message to the ticket. A public reply is emailed to the customer by the workspace's reply automation and moves the ticket according to its reply rules; an internal note (internal: true) is visible only to the team. Optionally set the status in the same call.

Whether a public reply reaches the customer depends on the workspace's automations, exactly as it does for a reply from the inbox. If autoAssignOnReply is on and the ticket is unassigned, the member behind the key becomes the assignee.

Request body

FieldTypeDescription
bodyrequiredstringPlain text.
internalbooleantrue for an internal note the customer never sees. Default false.
statusstringSet the ticket status at the same time, by value or label.

Responses

StatusMeaning
201Body: { message, ticket }.
404No ticket with that id.

Example request

curl -X POST https://crowdstack.org/api/v1/tickets/cmf3k2x9a0001abcd/messages \
  -H "Authorization: Bearer $CROWDSTACK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Hi Jane, thanks for flagging this. Which date range were you exporting?",
    "status": "pending"
  }'

Example response

{
  "message": {
    "id": "cmf3k2x9a0110abcd",
    "body": "Hi Jane, thanks for flagging this. Which date range were you exporting?",
    "authorType": "agent",
    "author": {
      "id": "cmf3k2x9a0003abcd",
      "name": "Jane Doe",
      "email": "jane@acme-mail.com"
    },
    "isInternal": false,
    "attachments": [],
    "createdAt": "2026-09-15T10:20:00.000Z"
  },
  "ticket": {
    "id": "cmf3k2x9a0100abcd",
    "number": 3243,
    "key": "#3243",
    "subject": "Cannot export invoices",
    "status": "pending",
    "priority": "high",
    "summary": null,
    "tags": [
      "billing"
    ],
    "fields": {},
    "contact": {
      "id": "cmf3k2x9a0001abcd",
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane@acme.com"
    },
    "assignee": {
      "id": "cmf3k2x9a0003abcd",
      "name": "Jane Doe",
      "email": "jane@acme-mail.com"
    },
    "team": null,
    "cc": [],
    "messageCount": 2,
    "sla": {
      "firstReplyDueAt": "2026-09-15T14:12:00.000Z",
      "resolveDueAt": "2026-09-17T10:12:00.000Z",
      "firstReplyBreachedAt": null,
      "resolveBreachedAt": null
    },
    "firstAgentReplyAt": null,
    "resolvedAt": null,
    "statusChangedAt": "2026-09-15T10:12:00.000Z",
    "createdAt": "2026-09-15T10:12:00.000Z",
    "updatedAt": "2026-09-15T10:12:00.000Z"
  }
}