All endpoints return JSON. Errors share one shape:
{ "message": "...", "errors": { ... } }.
GET
/tickets
scope: tickets:read
Paginated list of tickets, newest activity first.
Parameters
| Name | In | Type | Description |
| status |
query |
string |
Filter by status (new, open, pending, resolved, closed, spam). |
| per_page |
query |
integer |
Items per page (1–100, default 25). |
| page |
query |
integer |
Page number (default 1). |
Request
curl -H "X-API-Key: $KVIX_KEY" \
https://app.kvix.ai/api/v1/tickets?status=open&per_page=10
Response
{
"data": [
{
"id": 18,
"reference_code": "TKT-AC-00018",
"subject": "Refund question",
"status": "open",
"priority": "normal",
"channel": "email",
"assigned_to": null,
"tags": ["billing"],
"first_response_at": null,
"resolved_at": null,
"closed_at": null,
"last_activity_at": "2026-05-15T09:14:02+00:00",
"created_at": "2026-05-15T08:55:11+00:00"
}
],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "per_page": 10, "total": 28 }
}
POST
/tickets
scope: tickets:write
Create a new ticket. Customer is matched by email or auto-created.
Parameters
| Name | In | Type | Description |
| email |
body |
string |
Customer email (required). |
| subject |
body |
string |
Ticket subject (required). |
| body |
body |
string |
Opening message body (required). |
| name |
body |
string |
Customer display name (optional). |
| brand_id |
body |
integer |
Target brand id. Required for company-wide keys when the company has no default brand. |
Request
curl -H "X-API-Key: $KVIX_KEY" \
-H 'Content-Type: application/json' \
-X POST https://app.kvix.ai/api/v1/tickets \
-d '{"email":"[email protected]","subject":"Hello","body":"My order is late."}'
Response
{
"data": {
"id": 142,
"reference_code": "TKT-AC-00142",
"subject": "Hello",
"status": "new",
"channel": "api",
"customer": { "id": 88, "email": "[email protected]", "name": null },
"brand": { "id": 3, "slug": "default", "name": "Acme Support" }
}
}
GET
/tickets/{id}
scope: tickets:read
A single ticket plus its full message thread.
Parameters
| Name | In | Type | Description |
| id |
path |
integer |
The ticket id. |
Request
curl -H "X-API-Key: $KVIX_KEY" https://app.kvix.ai/api/v1/tickets/142
Response
{
"data": {
"id": 142,
"subject": "Hello",
"status": "open",
"messages": [
{ "id": 401, "sender_type": "customer", "body": "My order is late." },
{ "id": 402, "sender_type": "member", "body": "Sorry — let me check." }
]
}
}
PATCH
/tickets/{id}
scope: tickets:write
Update one or more of: status, priority, assignee, tags. Returns the refreshed ticket.
Parameters
| Name | In | Type | Description |
| status |
body |
string |
One of: new, open, pending, resolved, closed, spam. Moving to resolved/closed timestamps the ticket. |
| priority |
body |
string |
One of: low, normal, high, urgent. |
| assigned_to |
body |
integer|null |
User id of a member in your company, or null to unassign. |
| tags |
body |
array |
Array of tag strings; replaces the existing set. |
Request
curl -H "X-API-Key: $KVIX_KEY" \
-H 'Content-Type: application/json' \
-X PATCH https://app.kvix.ai/api/v1/tickets/142 \
-d '{"status":"resolved"}'
Response
{
"data": {
"id": 142,
"status": "resolved",
"resolved_at": "2026-05-15T10:02:18+00:00"
}
}
GET
/tickets/{id}/messages
scope: messages:read
Paginated message list for a ticket, oldest first.
Parameters
| Name | In | Type | Description |
| id |
path |
integer |
The ticket id. |
| per_page |
query |
integer |
Items per page (1–200, default 50). |
Request
curl -H "X-API-Key: $KVIX_KEY" https://app.kvix.ai/api/v1/tickets/142/messages
Response
{
"data": [
{ "id": 401, "sender_type": "customer", "body": "My order is late.", "is_internal_note": false },
{ "id": 402, "sender_type": "member", "body": "Sorry — let me check.", "is_internal_note": false }
],
"meta": { "current_page": 1, "per_page": 50, "total": 2 }
}
POST
/tickets/{id}/messages
scope: messages:write
Append a member reply or internal note. A non-note reply on a resolved ticket reopens it.
Parameters
| Name | In | Type | Description |
| body |
body |
string |
Message body (required, max 65535 chars). |
| is_internal_note |
body |
boolean |
Default false. Set true to add a note visible only to members. |
Request
curl -H "X-API-Key: $KVIX_KEY" \
-H 'Content-Type: application/json' \
-X POST https://app.kvix.ai/api/v1/tickets/142/messages \
-d '{"body":"Thanks for your patience — refund issued."}'
Response
{
"data": {
"id": 403,
"ticket_id": 142,
"sender_type": "member",
"body": "Thanks for your patience — refund issued.",
"is_internal_note": false,
"ai_generated": false,
"created_at": "2026-05-15T10:05:01+00:00"
}
}