Skip to main content

Create and update tickets API

Use these APIs to keep Filum tickets in step with records in another system, for example creating a ticket when a support request is raised in your store platform and updating it as that request changes.

Each ticket can carry an external_id: the ID of the matching record in your system. Filum keeps it unique within your organization, so you can:

  • Create safely: sending the same create twice (for example, when a webhook is retried) returns the ticket created the first time instead of a duplicate.
  • Update without storing Filum's ID: read and update a ticket by your own ID through the /by-external-id/{external_id} endpoints.

Every response also returns the Filum ticket id and url, so you can store them on your side if you want a link in both directions.

Prerequisites​

To use the APIs, you need to have a token. Tokens can be generated by an admin at the setting section in Filum CX platform. Ensure you have the necessary permissions to access the admin settings for token generation.

Token permissions​

A token can do only what the roles ticked under Role (Phân quyền) allow when it is created in Settings → Personal → Access Token → Create Access Token. The ticket APIs check these permissions from the role's Ticket (Phiếu yêu cầu) section:

Permission (Vietnamese label)Needed for
Create ticket (Tạo phiếu yêu cầu)POST /external/tickets
View assigned ticket (Xem phiếu yêu cầu được giao), or higherThe GET and PATCH endpoints

A token can always read and update the tickets it created, even after they are assigned to an agent. To read or update tickets created another way, for example by agents in Filum, give it View ticket list (Xem danh sách phiếu yêu cầu) instead.

Of the default roles, Admin (Quản trị viên) and Customer experience (Trải nghiệm khách hàng) include these permissions. Customer service (Dịch vụ khách hàng), View only (Chỉ xem) and Export (Xuất) do not include Create ticket, so their tokens are refused with 403 Missing permission Ticket.Create. Your workspace may have changed these roles, or added its own; check the role's Ticket section under Settings → Workspace → Access → Roles (Cài đặt → Không gian làm việc → Quyền truy cập → Phân quyền).

We recommend creating a dedicated role with just the permissions above for your integration, rather than giving the token the Admin role. The person creating the token must themselves hold every permission in the roles they tick.

Tickets created through the API are recorded as created by the account that generated the token, and every change is written to the ticket's activity log under that account.

APIs​

Access the APIs via the endpoint: https://api.filum.ai/

MethodPathSummary
POST/external/ticketsCreate a ticket
GET/external/tickets/{ticket_id}Get a ticket by its Filum ID
GET/external/tickets/by-external-id/{external_id}Get a ticket by your external ID
PATCH/external/tickets/{ticket_id}Update a ticket by its Filum ID
PATCH/external/tickets/by-external-id/{external_id}Update a ticket by your external ID

Header Parameters​

All endpoints take the same headers.

NameDescriptionRequiredSchema
authorizationThe authorization token to validate the request. The value must be in the format Bearer <your_api_token>Yesstring
organization-idThe unique identifier of your organizationYesstring
auth-typeThe type of authorization used for the request. The value must be tokenYesstring
content-typeThe content type of the request body. The value must be application/json (POST and PATCH only)Yesstring

POST /external/tickets​

Summary​

Create a ticket.

If external_id has already been used in your organization, nothing is created: the existing ticket is returned unchanged with status 200 instead of 201, and no notification or activity is recorded. To change that ticket, use the PATCH endpoints.

An external_id stays taken after its ticket is deleted in Filum: creating with it again answers 409, and the GET and PATCH endpoints answer 404 for it. The same 409 comes back when the existing ticket is one your token is not allowed to see.

Request Body​

FieldTypeRequiredDescription
subjectstringYesTicket subject, 1–255 characters
descriptionstringNoTicket description, up to 4000 characters
external_idstringNoThe ID of the matching record in your system, unique within your organization. 1–128 characters from A–Z a–z 0–9 . _ : -
statusstringNoStatus key. Defaults to new. See Statuses
prioritystringNoOne of low, medium, high, urgent. Defaults to low
due_datestring (ISO 8601 datetime)NoDue date. Include a timezone offset, e.g. 2026-10-25T17:00:00+07:00; a value without one is read as UTC
assignee_account_idintegerNoAccount ID of the agent to assign the ticket to
team_idintegerNoID of the team to assign the ticket to
user_idstringNoFilum ID of the customer the ticket is about
user_namestringNoCustomer name
user_phonestringNoCustomer phone number
user_emailstringNoCustomer email
installed_source_idintegerNoID of the installed channel the ticket belongs to
transaction_idstringNoA reference such as an order number. Tickets can be searched by it in Filum
custom_fieldsobjectNoCustom field values keyed by custom field ID. See Custom fields

Request body sample:

{
"external_id": "hrv-req-1001",
"subject": "Đổi size áo",
"description": "Khách muốn đổi từ M sang L",
"priority": "high",
"due_date": "2026-10-25T17:00:00+07:00",
"user_name": "Nguyễn Văn A",
"user_phone": "0901234567",
"user_email": "a@example.com",
"transaction_id": "ORD-20261019-001",
"custom_fields": {
"12": "Đổi trả"
}
}

Responses​

CodeDescriptionContent type
201Ticket createdapplication/json
200A ticket with this external_id already exists and is returned unchangedapplication/json
400Invalid value, e.g. unknown status, invalid custom field option, inactive installed channel, empty value for a required custom fieldapplication/json
401Unauthorizedapplication/json
403Forbiddenapplication/json
404A referenced custom field does not existapplication/json
409The external_id is taken by a deleted ticket, or by one your token cannot seeapplication/json
422Validation Errorapplication/json
429Too Many Requestsapplication/json

Both 201 and 200 return a Ticket object.

GET /external/tickets/{ticket_id}​

GET /external/tickets/by-external-id/{external_id}​

Summary​

Get one ticket, by its Filum ID or by your external ID.

Path Parameters​

NameDescriptionRequiredSchema
ticket_idThe Filum ticket IDYesinteger
external_idThe external_id the ticket was created withYesstring

Responses​

CodeDescriptionContent type
200Successful Responseapplication/json
401Unauthorizedapplication/json
403Forbiddenapplication/json
404No ticket with this ID in your organizationapplication/json
429Too Many Requestsapplication/json

200 returns a Ticket object.

PATCH /external/tickets/{ticket_id}​

PATCH /external/tickets/by-external-id/{external_id}​

Summary​

Update a ticket, by its Filum ID or by your external ID.

Only the fields present in the request body are changed; every field you leave out keeps its current value. Send null to clear an optional field.

Status changes follow the status rules: for example, a new ticket must be moved to open before it can be solved.

Path Parameters​

Same as the GET endpoints.

Request Body​

FieldTypeCan be nullDescription
subjectstringNoTicket subject, 1–255 characters
descriptionstringYesTicket description, up to 4000 characters
statusstringNoStatus key. See Statuses
prioritystringNoOne of low, medium, high, urgent
due_datestring (ISO 8601 datetime)YesDue date, with a timezone offset
assignee_account_idintegerYesAccount ID of the agent to assign; null unassigns
team_idintegerYesID of the team to assign; null removes the team
custom_fieldsobjectYes, per fieldCustom field values to change, keyed by custom field ID. Fields not listed keep their values; a field set to null is cleared

Request body sample (mark the ticket solved when the request is resolved):

{
"status": "solved",
"custom_fields": {
"12": "Đã đổi hàng"
}
}

Responses​

CodeDescriptionContent type
200Successful Responseapplication/json
400Invalid value, e.g. unknown status, a status change the status rules do not allow, invalid custom field optionapplication/json
401Unauthorizedapplication/json
403Forbiddenapplication/json
404No ticket with this ID, or an unknown custom fieldapplication/json
422Validation Error, e.g. null sent for statusapplication/json
429Too Many Requestsapplication/json

200 returns the updated Ticket object.

Ticket object​

FieldTypeDescription
idintegerFilum ticket ID
external_idstring | nullYour external ID, if the ticket was created with one
urlstringLink to the ticket in the Filum CX platform
subjectstringTicket subject
descriptionstring | nullTicket description
statusstringStatus key
prioritystringlow, medium, high or urgent
due_datestring | nullDue date, in UTC
assignee_account_idinteger | nullAccount ID of the assigned agent
team_idinteger | nullID of the assigned team
installed_source_idinteger | nullID of the installed channel
user_idstring | nullFilum ID of the customer
user_namestring | nullCustomer name
user_phonestring | nullCustomer phone number
user_emailstring | nullCustomer email
custom_fieldsobjectCustom field values keyed by custom field ID
createdstring (ISO 8601 datetime)When the ticket was created, in UTC
updatedstring (ISO 8601 datetime)When the ticket was last updated, in UTC

Response sample:

{
"id": 355,
"external_id": "hrv-req-1001",
"url": "https://cx.filum.ai/tickets/355",
"subject": "Đổi size áo",
"description": "Khách muốn đổi từ M sang L",
"status": "new",
"priority": "high",
"due_date": "2026-10-25T10:00:00+00:00",
"assignee_account_id": null,
"team_id": null,
"installed_source_id": null,
"user_id": null,
"user_name": "Nguyễn Văn A",
"user_phone": "0901234567",
"user_email": "a@example.com",
"custom_fields": {
"12": "Đổi trả"
},
"created": "2026-10-19T08:51:28.854284+00:00",
"updated": "2026-10-19T08:51:28.854288+00:00"
}

Statuses​

Every organization starts with five statuses: new, open, pending, solved and closed. Admins can add their own in Filum's ticket settings, so the valid set is specific to your organization. An unknown status is rejected with 400, and the error message lists the statuses available to you:

{
"detail": {
"message": "'waiting' is not a valid ticket status for this organization. Available: closed, new, open, pending, solved.",
"params": null
}
}

Status changes on update follow these rules, and are rejected with 400 otherwise:

  • A ticket can never be moved back to new. Create the ticket with the status you want if it should not start as new.
  • A new ticket can only be moved to open. Move it to open first, then to pending, solved or closed.
  • Once a ticket is closed, its status can no longer be changed.

Custom fields​

custom_fields is keyed by the custom field's ID, as a string.

  • Text fields take any string.
  • Single choice fields take one of the field's option values, exactly as written, or the option's ID prefixed with @ (for example "@101"), which keeps working if the option is later renamed.

A custom field marked as required in Filum cannot be set to null or an empty value; the request is rejected with 400.

Ask your Filum admin or your Filum contact for the IDs of the custom fields, options, agents and teams you need to map.

Integration example​

Mirroring support requests from another platform:

  1. A request is created → POST /external/tickets with external_id set to the request ID. If your platform retries the webhook, the retry gets 200 and the same ticket back.
  2. The request changes (new status, reassigned, a field edited) → PATCH /external/tickets/by-external-id/{request_id} with only the fields that changed. Remember a new ticket goes to open before any other status; if your platform's requests skip that step, create the ticket as open.
  3. You need the current state → GET /external/tickets/by-external-id/{request_id}.

Rate Limiting​

The ticket APIs share one rate limit per organization, separate from the export APIs:

  • Per second: 5 requests
  • Per minute: 50 requests

If you exceed these limits, you will receive a 429 Too Many Requests response. Please implement appropriate retry logic with exponential backoff in your integration.

Error Responses​

403 Forbidden​

The token's roles lack a permission the endpoint needs (see Prerequisites):

{
"detail": {
"message": "Missing permission {{resource}}.{{action}}. Please contact your workspace admin for more information",
"params": {
"resource": "Ticket",
"action": "Create"
}
}
}

404 Not Found​

{
"detail": {
"message": "{{model}} not found",
"params": {
"model": "ticket"
}
}
}

409 Conflict​

{
"detail": {
"message": "external_id is already used by a ticket that was deleted or that this token cannot access",
"params": null
}
}

params.model is ticket custom field when the missing object is a custom field.

422 Validation Error​

{
"detail": [
{
"loc": ["body", "status"],
"msg": "status cannot be left empty",
"type": "value_error"
}
]
}

429 Too Many Requests​

{
"detail": "Rate limit exceeded"
}