Reference: Tickets
Tickets, their panels and menus, and saved transcripts.
Good to know
Authorization: Bearer tfy_…. Replace YOUR_SERVER_ID with your Discord server id. Errors are explained in Requests, errors and limits.GET /tickets
GET /guilds/{guildId}/tickets
The list, filterable by state, panel, opener and claimant.
| Key permission | tickets.read (See tickets) |
Query parameters
Added to the address after a ?, like ?limit=10&order=asc.
| Field | Type | Required | What it is |
|---|---|---|---|
limit | integer | No | How many to answer with at most, 1 to 100.1 to 100 · default 25 |
cursor | string | No | The nextCursor of the page before, to get the next page. Absent: the first page.at most 64 characters |
order | "asc" | "desc" | No | desc for newest first, asc for oldest first.default "desc" |
state | "open" | "closed" | "deleted" | No | Only tickets in this state, such as open. |
panelId | string | No | Only tickets from this panel.at most 40 characters |
openerDiscordUserId | string | No | Only tickets this member opened.digits only |
claimedBy | string | No | Only tickets claimed by this person (a Technified user id).at most 40 characters |
q | string | No | Words in the reason or the opener’s name.at most 100 characters |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets" \
-H "Authorization: Bearer $TECHNIFIED_KEY"{
"items": [
{
"id": "tkt_01M5TXYM1CHGR14TA8A0PR6YX4",
"number": 12,
"panelId": null,
"channelId": null,
"channelName": "ticket-12",
"openerDiscordUserId": "17929789298638349990005",
"reason": "I was scammed in game",
"source": "panel",
"submissionId": null,
"state": "open",
"claimedBy": null,
"claimedAt": null,
"participants": [],
"closedBy": null,
"closedAt": null,
"closeReason": null,
"lastActivityAt": "2026-10-26T01:42:11.756Z",
"createdAt": "2026-10-26T01:42:11.756Z"
}
],
"nextCursor": null
}POST /tickets
POST /guilds/{guildId}/tickets
Opens one.
| Key permission | Any key of this server. |
| Retry safely | Send an Idempotency-Key header; a retry with the same one is not done twice. |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
panelId | string | No | The panel whose settings the ticket opens with.at most 40 characters |
discordUserId | string | No | The member the ticket is for (Discord user id). Absent: the caller.digits only |
reason | string or null | No | What it is about. Staff see it first.at most 1000 characters · default null |
source | "panel" | "menu" | "submission" | "command" | "api" | No | Where it came from, for the record. Leave it out.default "api" |
submissionId | string | No | The submission the ticket continues, if any.at most 40 characters |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'GET /tickets/{ticketId}
GET /guilds/{guildId}/tickets/{ticketId}
One ticket.
| Key permission | tickets.read (See tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"DELETE /tickets/{ticketId}
DELETE /guilds/{guildId}/tickets/{ticketId}
Saves a transcript, then deletes the channel. Refused with transcript_failed when the transcript cannot be saved.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
No request body.
Example
curl -X DELETE "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/{ticketId}/claim
POST /guilds/{guildId}/tickets/{ticketId}/claim
Takes responsibility for it. ?takeOver=true takes it from whoever had it. The Claim button in the channel becomes "Claimed by …".
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
Query parameters
Added to the address after a ?, like ?limit=10&order=asc.
| Field | Type | Required | What it is |
|---|---|---|---|
takeOver | "true" | "false" | No | true to take a ticket somebody else claimed. Otherwise that is refused.default "false" |
No request body.
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/claim" \
-H "Authorization: Bearer $TECHNIFIED_KEY"DELETE /tickets/{ticketId}/claim
DELETE /guilds/{guildId}/tickets/{ticketId}/claim
Hands it back. The button says Claim again.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
No request body.
Example
curl -X DELETE "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/claim" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/{ticketId}/close
POST /guilds/{guildId}/tickets/{ticketId}/close
Closes it, saving a transcript unless told not to. A transcript that fails is reported in transcriptError, and what Discord refused in discord; neither undoes the close.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
reason | string or null | No | Why it was closed. Kept with the ticket and posted in the channel.at most 1000 characters · default null |
saveTranscript | boolean | No | Save a transcript now. Absent: whatever the ticket’s panel says. |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/close" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{}'POST /tickets/{ticketId}/participants
POST /guilds/{guildId}/tickets/{ticketId}/participants
Lets somebody into the ticket.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
discordUserId | string | Yes | The Discord user id of the person to add.digits only |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/participants" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{"discordUserId":"123456789012345678"}'DELETE /tickets/{ticketId}/participants/{discordUserId}
DELETE /guilds/{guildId}/tickets/{ticketId}/participants/{discordUserId}
Takes somebody out. The opener can never be removed.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
discordUserId | string | Yes | A Discord user id (digits). |
No request body.
Example
curl -X DELETE "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/participants/DISCORDUSERID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/{ticketId}/reopen
POST /guilds/{guildId}/tickets/{ticketId}/reopen
Opens it again.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
No request body.
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/reopen" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/{ticketId}/transcript
POST /guilds/{guildId}/tickets/{ticketId}/transcript
Saves a transcript now.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
ticketId | string | Yes | A ticket’s id (tkt_…). |
No request body.
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/TICKETID/transcript" \
-H "Authorization: Bearer $TECHNIFIED_KEY"GET /tickets/menus
GET /guilds/{guildId}/tickets/menus
| Key permission | tickets.read (See tickets) |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/menus" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/menus
POST /guilds/{guildId}/tickets/menus
| Key permission | tickets.write (Handle tickets) |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
name | string | Yes | 1 to 60 characters |
title | string | Yes | 1 to 120 characters |
description | string or null | No | at most 2000 characters · default null |
placeholder | string | No | 1 to 100 characters · default "Choose a topic" |
panelIds | array of string | Yes | 1 to 25 items |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/menus" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","title":"…","panelIds":["…"]}'PATCH /tickets/menus/{menuId}
PATCH /guilds/{guildId}/tickets/menus/{menuId}
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
menuId | string | Yes | A ticket menu’s id (mnu_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
name | string | No | 1 to 60 characters |
title | string | No | 1 to 120 characters |
description | string or null | No | at most 2000 characters · default null |
placeholder | string | No | 1 to 100 characters · default "Choose a topic" |
panelIds | array of string | No | 1 to 25 items |
Example
curl -X PATCH "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/menus/MENUID" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{}'DELETE /tickets/menus/{menuId}
DELETE /guilds/{guildId}/tickets/menus/{menuId}
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
menuId | string | Yes | A ticket menu’s id (mnu_…). |
No request body.
Example
curl -X DELETE "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/menus/MENUID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/menus/{menuId}/publish
POST /guilds/{guildId}/tickets/menus/{menuId}/publish
Posts the menu into a channel. A copy posted before is taken down.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
menuId | string | Yes | A ticket menu’s id (mnu_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
channelId | string | Yes | The Discord channel id to post it in.digits only |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/menus/MENUID/publish" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{"channelId":"123456789012345678"}'GET /tickets/panels
GET /guilds/{guildId}/tickets/panels
| Key permission | tickets.read (See tickets) |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/panels" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/panels
POST /guilds/{guildId}/tickets/panels
| Key permission | tickets.write (Handle tickets) |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
name | string | Yes | 1 to 60 characters |
title | string | Yes | 1 to 120 characters |
description | string or null | No | at most 2000 characters · default null |
buttonLabel | string | No | 1 to 60 characters · default "Open a ticket" |
buttonStyle | "primary" | "secondary" | "success" | "danger" | No | default "primary" |
buttonEmoji | string or null | No | at most 64 characters · default null |
categoryId | string or null | No | digits only · default null |
namingPattern | string | No | 1 to 60 characters · default "ticket-{number}" |
welcomeMessage | string or null | No | at most 2000 characters · default null |
reasonRequired | boolean | No | default false |
maxOpenPerMember | integer | No | 1 to 25 · default 1 |
autoCloseAfterHours | integer or null | No | 1 to 720 · default null |
deleteClosedAfterHours | integer or null | No | 1 to 720 · default 24 |
saveTranscriptOnClose | boolean | No | default true |
staffRoleIds | array of string | No | at most 25 items · default [] |
message | object, one of the shapes below or null | No | default null |
message takes one of these shapes:
kind: "embed"
| Field | Type | Required | What it is |
|---|---|---|---|
kind | "embed" | Yes | |
content | string or null | No | at most 2000 characters · default null |
embed | object or null | No | default null |
embed.author | string or null | No | at most 256 characters · default null |
embed.title | string or null | No | at most 256 characters · default null |
embed.titleUrl | string or null | No | at most 500 characters · default null |
embed.description | string or null | No | at most 4000 characters · default null |
embed.colour | string or null | No | default null |
embed.fields | array of objects | No | at most 25 items · default [] |
embed.fields[].name | string | Yes | 1 to 256 characters |
embed.fields[].value | string | Yes | 1 to 1024 characters |
embed.fields[].inline | boolean | No | default false |
embed.imageUrl | string or null | No | at most 500 characters · default null |
embed.thumbnailUrl | string or null | No | at most 500 characters · default null |
embed.footer | string or null | No | at most 2048 characters · default null |
kind: "components"
| Field | Type | Required | What it is |
|---|---|---|---|
kind | "components" | Yes | |
components | object | Yes | |
components.boxed | boolean | No | |
components.accentColour | string or null | No | default null |
components.spoiler | boolean | No | default false |
components.blocks | array of object, one of the shapes below | Yes | at most 30 items |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/panels" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","title":"…"}'PATCH /tickets/panels/{panelId}
PATCH /guilds/{guildId}/tickets/panels/{panelId}
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
panelId | string | Yes | A ticket panel’s id (pnl_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
name | string | No | 1 to 60 characters |
title | string | No | 1 to 120 characters |
description | string or null | No | at most 2000 characters · default null |
buttonLabel | string | No | 1 to 60 characters · default "Open a ticket" |
buttonStyle | "primary" | "secondary" | "success" | "danger" | No | default "primary" |
buttonEmoji | string or null | No | at most 64 characters · default null |
categoryId | string or null | No | digits only · default null |
namingPattern | string | No | 1 to 60 characters · default "ticket-{number}" |
welcomeMessage | string or null | No | at most 2000 characters · default null |
reasonRequired | boolean | No | default false |
maxOpenPerMember | integer | No | 1 to 25 · default 1 |
autoCloseAfterHours | integer or null | No | 1 to 720 · default null |
deleteClosedAfterHours | integer or null | No | 1 to 720 · default 24 |
saveTranscriptOnClose | boolean | No | default true |
staffRoleIds | array of string | No | at most 25 items · default [] |
message | object, one of the shapes below or null | No | default null |
message takes one of these shapes:
kind: "embed"
| Field | Type | Required | What it is |
|---|---|---|---|
kind | "embed" | Yes | |
content | string or null | No | at most 2000 characters · default null |
embed | object or null | No | default null |
embed.author | string or null | No | at most 256 characters · default null |
embed.title | string or null | No | at most 256 characters · default null |
embed.titleUrl | string or null | No | at most 500 characters · default null |
embed.description | string or null | No | at most 4000 characters · default null |
embed.colour | string or null | No | default null |
embed.fields | array of objects | No | at most 25 items · default [] |
embed.fields[].name | string | Yes | 1 to 256 characters |
embed.fields[].value | string | Yes | 1 to 1024 characters |
embed.fields[].inline | boolean | No | default false |
embed.imageUrl | string or null | No | at most 500 characters · default null |
embed.thumbnailUrl | string or null | No | at most 500 characters · default null |
embed.footer | string or null | No | at most 2048 characters · default null |
kind: "components"
| Field | Type | Required | What it is |
|---|---|---|---|
kind | "components" | Yes | |
components | object | Yes | |
components.boxed | boolean | No | |
components.accentColour | string or null | No | default null |
components.spoiler | boolean | No | default false |
components.blocks | array of object, one of the shapes below | Yes | at most 30 items |
Example
curl -X PATCH "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/panels/PANELID" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{}'DELETE /tickets/panels/{panelId}
DELETE /guilds/{guildId}/tickets/panels/{panelId}
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
panelId | string | Yes | A ticket panel’s id (pnl_…). |
No request body.
Example
curl -X DELETE "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/panels/PANELID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"POST /tickets/panels/{panelId}/publish
POST /guilds/{guildId}/tickets/panels/{panelId}/publish
Posts the panel into a channel.
| Key permission | tickets.write (Handle tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
panelId | string | Yes | A ticket panel’s id (pnl_…). |
Request body
JSON, sent with Content-Type: application/json.
| Field | Type | Required | What it is |
|---|---|---|---|
channelId | string | Yes | The Discord channel id to post it in.digits only |
Example
curl -X POST "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/panels/PANELID/publish" \
-H "Authorization: Bearer $TECHNIFIED_KEY" \
-H "Content-Type: application/json" \
-d '{"channelId":"123456789012345678"}'GET /tickets/transcripts
GET /guilds/{guildId}/tickets/transcripts
Saved transcripts, newest first, with a cursor.
| Key permission | tickets.read (See tickets) |
Query parameters
Added to the address after a ?, like ?limit=10&order=asc.
| Field | Type | Required | What it is |
|---|---|---|---|
limit | integer | No | How many to answer with at most, 1 to 100.1 to 100 · default 25 |
cursor | string | No | The nextCursor of the page before.at most 40 characters |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/transcripts" \
-H "Authorization: Bearer $TECHNIFIED_KEY"GET /tickets/transcripts/{transcriptId}
GET /guilds/{guildId}/tickets/transcripts/{transcriptId}
One transcript, as a self contained HTML page.
| Key permission | tickets.read (See tickets) |
In the address
| Field | Type | Required | What it is |
|---|---|---|---|
transcriptId | string | Yes | A transcript’s id (trs_…). |
No request body.
Example
curl -X GET "https://api.technified.xyz/v1/guilds/YOUR_SERVER_ID/tickets/transcripts/TRANSCRIPTID" \
-H "Authorization: Bearer $TECHNIFIED_KEY"Still stuck? Get help from the Technified team.