Tickets

Tickets are the core entity in Keme. Every player support interaction — whether it arrives via the in-game SDK, Discord, Steam, email, or the REST API — creates a ticket. This reference covers creation, retrieval, status and priority updates, assignment, resolution, and deletion.

Tickets are workspace-scoped. All write operations require a valid Authorization: Bearer header using a workspace secret key. Read operations also support read-only API keys with the tickets:read scope.

Note:Keme automatically triages every new ticket with its AI engine. The aiTriaged, aiSuggestedCategory, aiConfidence, and aiSuggestedReply fields are populated within seconds of creation and are read-only.

The Ticket Object

A ticket object is returned by all endpoints that interact with individual tickets. The table below describes the full set of fields.

FieldTypeDescription
idstringUnique ticket identifier. Prefix: tkt_.
workspaceIdstringThe workspace this ticket belongs to.
playerIdstringThe player who submitted the ticket.
titlestringShort summary of the issue (max 255 chars).
bodystringFull description of the issue.
statusenumopen | in_progress | resolved | closed
priorityenumlow | medium | high | urgent
categorystringSupport category (e.g. billing, gameplay, account).
sourceenumapi | sdk | discord | steam | email
tagsstring[]Arbitrary string labels for filtering and reporting.
metadataobjectCaller-defined key/value pairs (game version, platform, order IDs, etc.).
assigneeIdstring | nullID of the assigned support agent, or null if unassigned.
assigneeobject | nullExpanded agent object when the ticket is fetched individually.
aiTriagedbooleanWhether AI triage has completed for this ticket.
aiSuggestedCategorystring | nullCategory recommended by the AI triage engine.
aiConfidencenumber | nullConfidence score between 0 and 1 for the AI suggestion.
aiSuggestedReplystring | nullAI-drafted first reply. Only present on GET /v1/tickets/:id.
messagesarrayConversation thread. Only present on GET /v1/tickets/:id.
messageCountnumberTotal number of messages in the thread.
createdAtstringISO 8601 timestamp of ticket creation.
updatedAtstringISO 8601 timestamp of the last update.
resolvedAtstring | nullISO 8601 timestamp when the ticket was resolved, or null.
closedAtstring | nullISO 8601 timestamp when the ticket was closed, or null.

Status Lifecycle

Tickets move through a defined lifecycle. Valid transitions are shown below. Attempting an invalid transition returns a 422 Unprocessable Entity.

  • open — Initial state for all new tickets.
  • in_progress — An agent has been assigned and is actively working the issue.
  • resolved — The issue has been addressed. The player may re-open by replying.
  • closed — Terminal state. The ticket is archived and cannot be re-opened via reply.
Note:Tickets that remain resolved for 72 hours without a player reply are automatically transitioned to closed by the Keme automation engine. This threshold is configurable per workspace.

Endpoints

POST/v1/tickets🔒 Auth required

Create a new support ticket on behalf of a player. The AI triage engine will automatically categorise and draft a suggested reply within seconds of creation.

Request Body
ParameterTypeRequiredDescription
workspaceIdstringRequiredThe workspace to create the ticket in.
playerIdstringRequiredThe ID of the player submitting the ticket.
titlestringRequiredShort summary of the issue. Max 255 characters.
bodystringRequiredFull description of the issue written by the player.
categorystringOptionalSupport category (e.g. billing, gameplay, account, technical). If omitted, AI triage will suggest one.
priorityenumOptionallow | medium | high | urgent. Defaults to medium.
sourceenumOptionalapi | sdk | discord | steam | email. Defaults to api.
metadataobjectOptionalArbitrary key/value pairs to attach to the ticket (game version, platform, order IDs, etc.).
tagsstring[]OptionalArray of string labels for filtering and reporting.
Request
bash
1curl -X POST https://api.kemegames.com/v1/tickets \
2 -H "Authorization: Bearer sk_live_••••••••" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "workspaceId": "ws_01HXYZ123456",
6 "playerId": "plr_01HABC789012",
7 "title": "Cannot access purchased DLC after update",
8 "body": "After the v2.4.1 update I can no longer access the Starfall DLC I purchased last month. The content is missing from the main menu and my receipt is attached.",
9 "category": "billing",
10 "priority": "high",
11 "source": "sdk",
12 "tags": ["dlc", "billing", "v2.4.1"],
13 "metadata": {
14 "gameVersion": "2.4.1",
15 "platform": "steam",
16 "orderId": "S-98712345",
17 "dlcId": "dlc_starfall_pack"
18 }
19 }'
Response
201
json
1{
2 "id": "tkt_01HYZA456789",
3 "workspaceId": "ws_01HXYZ123456",
4 "playerId": "plr_01HABC789012",
5 "title": "Cannot access purchased DLC after update",
6 "body": "After the v2.4.1 update I can no longer access the Starfall DLC I purchased last month. The content is missing from the main menu and my receipt is attached.",
7 "status": "open",
8 "priority": "high",
9 "category": "billing",
10 "source": "sdk",
11 "tags": ["dlc", "billing", "v2.4.1"],
12 "metadata": {
13 "gameVersion": "2.4.1",
14 "platform": "steam",
15 "orderId": "S-98712345",
16 "dlcId": "dlc_starfall_pack"
17 },
18 "assigneeId": null,
19 "assignee": null,
20 "aiTriaged": true,
21 "aiSuggestedCategory": "billing",
22 "aiConfidence": 0.94,
23 "messageCount": 0,
24 "createdAt": "2026-06-15T09: 12: 34.000Z",
25 "updatedAt": "2026-06-15T09: 12: 34.000Z",
26 "resolvedAt": null,
27 "closedAt": null
28}
GET/v1/tickets🔒 Auth required

Return a paginated list of tickets for a workspace. Supports filtering by status, priority, category, assignee, and player, as well as full-text search across title and body.

Query Parameters
ParameterTypeRequiredDescription
workspaceIdstringRequiredFilter results to this workspace.
statusenumOptionalopen | in_progress | resolved | closed. Comma-separate for multiple values.
priorityenumOptionallow | medium | high | urgent. Comma-separate for multiple values.
categorystringOptionalFilter by support category.
assigneeIdstringOptionalReturn only tickets assigned to this agent ID. Pass unassigned to return tickets with no assignee.
playerIdstringOptionalReturn only tickets submitted by this player.
searchstringOptionalFull-text search across ticket title and body.
sortByenumOptionalcreatedAt | updatedAt | priority. Defaults to createdAt.
orderenumOptionalasc | desc. Defaults to desc.
limitintegerOptionalNumber of results per page. Min 1, max 100. Defaults to 25.
offsetintegerOptionalNumber of records to skip for pagination. Defaults to 0.
Request
bash
1curl "https://api.kemegames.com/v1/tickets?workspaceId=ws_01HXYZ123456&status=open&priority=high&sortBy=createdAt&order=desc&limit=20&offset=0" \
2 -H "Authorization: Bearer sk_live_••••••••"
Response
200
json
1{
2 "data": [
3 {
4 "id": "tkt_01HYZA456789",
5 "workspaceId": "ws_01HXYZ123456",
6 "playerId": "plr_01HABC789012",
7 "title": "Cannot access purchased DLC after update",
8 "status": "open",
9 "priority": "high",
10 "category": "billing",
11 "source": "sdk",
12 "tags": ["dlc", "billing", "v2.4.1"],
13 "assigneeId": null,
14 "aiTriaged": true,
15 "messageCount": 0,
16 "createdAt": "2026-06-15T09: 12: 34.000Z",
17 "updatedAt": "2026-06-15T09: 12: 34.000Z"
18 },
19 {
20 "id": "tkt_01HYBX654321",
21 "workspaceId": "ws_01HXYZ123456",
22 "playerId": "plr_01HDEF345678",
23 "title": "Matchmaking stuck in queue for 30+ minutes",
24 "status": "open",
25 "priority": "high",
26 "category": "gameplay",
27 "source": "discord",
28 "tags": ["matchmaking", "lag"],
29 "assigneeId": "agt_01HGHI901234",
30 "aiTriaged": true,
31 "messageCount": 3,
32 "createdAt": "2026-06-15T08: 47: 10.000Z",
33 "updatedAt": "2026-06-15T09: 01: 55.000Z"
34 }
35 ],
36 "pagination": {
37 "total": 142,
38 "limit": 20,
39 "offset": 0,
40 "hasMore": true
41 }
42}
GET/v1/tickets/:id🔒 Auth required

Retrieve a single ticket by ID. This endpoint returns the full ticket object including the complete message thread, expanded player and assignee objects, and the AI-suggested reply.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique ID of the ticket (prefix: tkt_).
Request
bash
1curl "https://api.kemegames.com/v1/tickets/tkt_01HYZA456789" \
2 -H "Authorization: Bearer sk_live_••••••••"
Response
200
json
1{
2 "id": "tkt_01HYZA456789",
3 "workspaceId": "ws_01HXYZ123456",
4 "playerId": "plr_01HABC789012",
5 "player": {
6 "id": "plr_01HABC789012",
7 "displayName": "QuantumViper",
8 "email": "player@example.com",
9 "platform": "steam",
10 "steamId": "76561198012345678",
11 "accountAge": "2y 4m",
12 "lifetimeSpend": 84.97,
13 "loyaltyTier": "gold"
14 },
15 "title": "Cannot access purchased DLC after update",
16 "body": "After the v2.4.1 update I can no longer access the Starfall DLC I purchased last month. The content is missing from the main menu and my receipt is attached.",
17 "status": "in_progress",
18 "priority": "high",
19 "category": "billing",
20 "source": "sdk",
21 "tags": ["dlc", "billing", "v2.4.1"],
22 "metadata": {
23 "gameVersion": "2.4.1",
24 "platform": "steam",
25 "orderId": "S-98712345",
26 "dlcId": "dlc_starfall_pack"
27 },
28 "assigneeId": "agt_01HGHI901234",
29 "assignee": {
30 "id": "agt_01HGHI901234",
31 "name": "Sara Chen",
32 "avatarUrl": "https://cdn.kemegames.com/avatars/agt_01HGHI901234.jpg"
33 },
34 "aiTriaged": true,
35 "aiSuggestedCategory": "billing",
36 "aiConfidence": 0.94,
37 "aiSuggestedReply": "Hi QuantumViper! I can see your Starfall DLC purchase from May 14. Let me verify the entitlement on our end and push a refresh to your account.",
38 "messages": [
39 {
40 "id": "msg_01HYZB111111",
41 "ticketId": "tkt_01HYZA456789",
42 "authorId": "plr_01HABC789012",
43 "authorType": "player",
44 "body": "Still no luck, tried reinstalling the DLC already.",
45 "createdAt": "2026-06-15T09: 45: 00.000Z"
46 },
47 {
48 "id": "msg_01HYZB222222",
49 "ticketId": "tkt_01HYZA456789",
50 "authorId": "agt_01HGHI901234",
51 "authorType": "agent",
52 "body": "Thanks for trying that. I have pushed an entitlement refresh — please restart Steam and let me know if it appears.",
53 "createdAt": "2026-06-15T10: 02: 17.000Z"
54 }
55 ],
56 "messageCount": 2,
57 "createdAt": "2026-06-15T09: 12: 34.000Z",
58 "updatedAt": "2026-06-15T10: 02: 17.000Z",
59 "resolvedAt": null,
60 "closedAt": null
61}
PATCH/v1/tickets/:id🔒 Auth required

Update one or more fields on an existing ticket. Only the fields included in the request body are modified — this is a partial update. All fields are optional.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique ID of the ticket to update.
Request Body
ParameterTypeRequiredDescription
statusenumOptionalNew status: open | in_progress | resolved | closed. Must follow valid lifecycle transitions.
priorityenumOptionalNew priority: low | medium | high | urgent.
assigneeIdstringOptionalAgent ID to assign the ticket to. Pass null to unassign.
categorystringOptionalUpdate the support category.
tagsstring[]OptionalReplace the full tags array. To clear all tags pass an empty array.
internalNotestringOptionalInternal note visible only to agents — not shown to the player.
Request
bash
1curl -X PATCH https://api.kemegames.com/v1/tickets/tkt_01HYZA456789 \
2 -H "Authorization: Bearer sk_live_••••••••" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "status": "in_progress",
6 "priority": "urgent",
7 "assigneeId": "agt_01HGHI901234",
8 "category": "billing",
9 "tags": ["dlc", "billing", "v2.4.1", "escalated"],
10 "internalNote": "Player has gold loyalty tier and $84 LTV — escalated to senior billing agent."
11 }'
Response
200
json
1{
2 "id": "tkt_01HYZA456789",
3 "status": "in_progress",
4 "priority": "urgent",
5 "category": "billing",
6 "assigneeId": "agt_01HGHI901234",
7 "tags": ["dlc", "billing", "v2.4.1", "escalated"],
8 "updatedAt": "2026-06-15T10: 15: 00.000Z"
9}
POST/v1/tickets/:id/assign🔒 Auth required

Assign a ticket to a specific support agent. This is a convenience endpoint that sets the assignee and automatically transitions status to in_progress if the ticket is currently open. An optional internal note is recorded in the audit log.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique ID of the ticket to assign.
Request Body
ParameterTypeRequiredDescription
agentIdstringRequiredThe ID of the agent to assign the ticket to.
notestringOptionalOptional internal note explaining the assignment decision. Visible only to agents.
Request
bash
1curl -X POST https://api.kemegames.com/v1/tickets/tkt_01HYZA456789/assign \
2 -H "Authorization: Bearer sk_live_••••••••" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "agentId": "agt_01HGHI901234",
6 "note": "Assigning to Sara — she handled the last three DLC entitlement issues this week."
7 }'
Response
200
json
1{
2 "id": "tkt_01HYZA456789",
3 "assigneeId": "agt_01HGHI901234",
4 "assignee": {
5 "id": "agt_01HGHI901234",
6 "name": "Sara Chen",
7 "avatarUrl": "https://cdn.kemegames.com/avatars/agt_01HGHI901234.jpg"
8 },
9 "status": "in_progress",
10 "internalNote": "Assigning to Sara — she handled the last three DLC entitlement issues this week.",
11 "updatedAt": "2026-06-15T10: 20: 00.000Z"
12}
POST/v1/tickets/:id/resolve🔒 Auth required

Mark a ticket as resolved. Optionally include a resolution note summarising the outcome, and choose whether to send the player an automated resolution notification.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique ID of the ticket to resolve.
Request Body
ParameterTypeRequiredDescription
resolutionNotestringOptionalInternal summary of how the issue was resolved. Stored in the ticket record.
sendNotificationbooleanOptionalWhen true, Keme sends the player a resolution notification via their original contact channel. Defaults to true.
Request
bash
1curl -X POST https://api.kemegames.com/v1/tickets/tkt_01HYZA456789/resolve \
2 -H "Authorization: Bearer sk_live_••••••••" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "resolutionNote": "Pushed an entitlement refresh via Steam API. Player confirmed DLC is now accessible. No further action needed.",
6 "sendNotification": true
7 }'
Response
200
json
1{
2 "id": "tkt_01HYZA456789",
3 "status": "resolved",
4 "resolutionNote": "Pushed an entitlement refresh via Steam API. Player confirmed DLC is now accessible. No further action needed.",
5 "notificationSent": true,
6 "resolvedAt": "2026-06-15T11: 05: 42.000Z",
7 "updatedAt": "2026-06-15T11: 05: 42.000Z"
8}
DELETE/v1/tickets/:id🔒 Auth required

Permanently delete a ticket and all associated messages, attachments, and audit events. This action cannot be undone.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique ID of the ticket to delete.
Warning:Deletion is permanent and irreversible. All messages, attachments, internal notes, and audit log entries for the ticket are destroyed. In most cases you should close the ticket instead — a closed ticket is archived but its history is preserved for compliance and reporting purposes.

Error Codes

All errors follow the standard Keme error envelope. The table below lists errors specific to the Tickets resource.

HTTP StatusError CodeDescription
400validation_errorA required field is missing or a field value is invalid.
401unauthorizedNo API key provided or the key is invalid.
403forbiddenThe API key does not have permission for this operation or workspace.
404ticket_not_foundNo ticket exists with the supplied ID in this workspace.
404agent_not_foundThe agentId supplied for assignment does not exist in this workspace.
404player_not_foundThe playerId supplied during ticket creation does not exist.
409ticket_already_closedCannot update a ticket that is in the closed terminal state.
422invalid_status_transitionThe requested status change does not follow the allowed lifecycle transitions.
429rate_limit_exceededYour workspace has exceeded its API rate limit. Retry after the duration in the Retry-After header.
Example error response
1{
2 "error": {
3 "code": "invalid_status_transition",
4 "message": "Cannot transition a ticket from 'closed' to 'open'. Closed tickets are terminal.",
5 "status": 422,
6 "requestId": "req_01HYZZ999888"
7 }
8}

Rate Limits

The Tickets API is subject to workspace-level rate limits. Limits are applied per API key and reset on a rolling 60-second window.

  • Starter plan: 120 requests / minute, 5,000 tickets / month
  • Growth plan: 600 requests / minute, 50,000 tickets / month
  • Scale plan: 3,000 requests / minute, unlimited tickets

When a rate limit is exceeded the API returns 429 Too Many Requests with a Retry-After header indicating the number of seconds to wait before retrying.

Last updated: June 15, 2026Edit this page