Platform
REST API
The Talki REST API lets you create tickets, post messages, and read organization data programmatically. All endpoints return JSON and use standard HTTP status codes.
Base URL
Authentication
All API requests must include your secret API key in the Authorization header. Find your key in Admin → API Keys.
# All requests require an Authorization header with your API key
curl https://api.talki.tech/v1/tickets \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"⚠Keep your secret key private
apiKey only for the widget snippet.Tickets
List tickets
Returns a paginated list of tickets for your organization.
GET /v1/tickets
GET /v1/tickets?status=open&page=1&per_page=25
# Response
{
"data": [
{
"id": "tkt_abc123",
"orgId": "org_xyz",
"status": "open",
"channel": "widget",
"subject": "Can't log into my account",
"createdAt": "2024-03-15T14:23:00Z",
"updatedAt": "2024-03-15T14:58:00Z",
"customer": {
"name": "Alice Johnson",
"email": "alice@example.com"
},
"assignedTo": "agent_123",
"tags": ["billing", "urgent"]
}
],
"meta": {
"total": 142,
"page": 1,
"perPage": 25
}
}Query parameters
| Name | Type | Description |
|---|---|---|
| status | "open" | "resolved" | "pending" | Filter tickets by status. |
| channel | string | Filter by channel: widget, email, telegram, api. |
| assignedTo | string | Filter by agent ID. Pass "unassigned" for unassigned tickets. |
| tag | string | Filter tickets with this tag. |
| page | number | Page number for pagination. |
| per_page | number | Results per page. Max 100. |
| sort | "created_asc" | "created_desc" | "updated_desc" | Sort order. |
Get ticket
Returns a single ticket with all messages.
GET /v1/tickets/:id
# Response
{
"id": "tkt_abc123",
"orgId": "org_xyz",
"status": "open",
"channel": "widget",
"subject": "Can't log into my account",
"createdAt": "2024-03-15T14:23:00Z",
"updatedAt": "2024-03-15T14:58:00Z",
"customer": {
"name": "Alice Johnson",
"email": "alice@example.com",
"userId": "usr_abc"
},
"messages": [
{
"id": "msg_001",
"role": "customer",
"text": "Hi, I can't log in using my Google account.",
"createdAt": "2024-03-15T14:23:00Z"
},
{
"id": "msg_002",
"role": "agent",
"text": "Hi Alice, let me look into that for you.",
"agentName": "Bob",
"createdAt": "2024-03-15T14:58:00Z"
}
]
}Create ticket
Creates a new ticket via the API channel.
POST /v1/tickets
Content-Type: application/json
{
"channel": "api",
"subject": "Password reset not working",
"customer": {
"name": "Bob Smith",
"email": "bob@example.com"
},
"message": "I clicked 'Forgot Password' but the email never arrived.",
"tags": ["password", "email-delivery"]
}
# Response: 201 Created
{
"id": "tkt_new456",
"status": "open",
...
}Update ticket
Update ticket status, assignment, or tags.
PATCH /v1/tickets/:id
Content-Type: application/json
{
"status": "resolved", // "open" | "resolved" | "pending"
"assignedTo": "agent_456", // agent ID
"tags": ["billing"]
}Messages
Post a message
Appends an agent message to an existing ticket. Delivered to the customer via their original channel (widget, email, or Telegram).
POST /v1/tickets/:id/messages
Content-Type: application/json
{
"text": "We've fixed the issue — please try again and let us know!"
}
# Response: 201 Created
{
"id": "msg_789",
"role": "agent",
"text": "We've fixed the issue — please try again!",
"createdAt": "2024-03-16T09:11:00Z"
}Error codes
| Status | Meaning |
|---|---|
| 200 OK | Request succeeded. |
| 201 Created | Resource created. Returns the new resource. |
| 400 Bad Request | Invalid request body. Check the error message for details. |
| 401 Unauthorized | Missing or invalid API key. |
| 403 Forbidden | API key lacks permission for this operation. |
| 404 Not Found | Resource not found or does not belong to your organization. |
| 429 Too Many Requests | Rate limit exceeded. Default: 300 req/min per key. |
| 500 Internal Server Error | Unexpected server error. Retry with exponential backoff. |
Rate limits
The default rate limit is 300 requests per minute per API key. When exceeded, the API returns HTTP 429 with a Retry-After header indicating when to retry. Limits reset on a rolling 60-second window.
