curl --request POST \
--url https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subject": "Export failing with 500",
"description": "Customer cannot export orders.",
"customer": {
"email": "jane@example.com",
"name": "Jane Doe"
},
"statusId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statusCategory": "new",
"assigneeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"assigneeEmail": "sam@example.com",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets"
payload = {
"subject": "Export failing with 500",
"description": "Customer cannot export orders.",
"customer": {
"email": "jane@example.com",
"name": "Jane Doe"
},
"statusId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statusCategory": "new",
"assigneeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"assigneeEmail": "sam@example.com",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
subject: 'Export failing with 500',
description: 'Customer cannot export orders.',
customer: {email: 'jane@example.com', name: 'Jane Doe'},
statusId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
statusCategory: 'new',
assigneeId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
assigneeEmail: 'sam@example.com',
teamId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'subject' => 'Export failing with 500',
'description' => 'Customer cannot export orders.',
'customer' => [
'email' => 'jane@example.com',
'name' => 'Jane Doe'
],
'statusId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'statusCategory' => 'new',
'assigneeId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'assigneeEmail' => 'sam@example.com',
'teamId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets"
payload := strings.NewReader("{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"ticketNumber": 123,
"subject": "<string>",
"description": "<string>",
"statusCategory": "on_customer",
"statusId": "<string>",
"assigneeId": "<string>",
"customer": {
"id": "<string>",
"name": "Ada Lovelace",
"email": "ada@example.com",
"phoneNumber": "<string>"
},
"metadata": {
"phone_number": "+1 525-525-5255"
},
"channel": "email",
"conversationId": "<string>",
"teamId": "<string>",
"createdAt": "2026-07-20T12:34:56.000Z",
"updatedAt": "2026-07-21T09:00:00.000Z",
"lastMessageAt": "2026-07-21T08:55:00.000Z"
}{
"error": {
"code": "VALIDATION_INVALID_BODY",
"message": "Invalid request"
}
}{
"error": {
"code": "AUTH_MISSING_API_KEY",
"message": "Authentication required"
}
}{
"error": {
"code": "SUBSCRIPTION_API_RESTRICTED_PLAN",
"message": "A Standard plan or higher is required to access the API"
}
}{
"error": {
"code": "AGENT_NOT_FOUND",
"message": "Agent not found"
}
}{
"error": {
"code": "TICKET_INVALID_STATUS",
"message": "The requested status could not be applied"
}
}{
"error": {
"code": "RATE_LIMIT_TOO_MANY_REQUESTS",
"message": "Too many requests, please try again later"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Something went wrong, please try again"
}
}Create a ticket
Creates a ticket on behalf of a customer. Unless an assignee is provided, the ticket is auto-assigned via the agent’s routing rules.
curl --request POST \
--url https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subject": "Export failing with 500",
"description": "Customer cannot export orders.",
"customer": {
"email": "jane@example.com",
"name": "Jane Doe"
},
"statusId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statusCategory": "new",
"assigneeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"assigneeEmail": "sam@example.com",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets"
payload = {
"subject": "Export failing with 500",
"description": "Customer cannot export orders.",
"customer": {
"email": "jane@example.com",
"name": "Jane Doe"
},
"statusId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statusCategory": "new",
"assigneeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"assigneeEmail": "sam@example.com",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
subject: 'Export failing with 500',
description: 'Customer cannot export orders.',
customer: {email: 'jane@example.com', name: 'Jane Doe'},
statusId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
statusCategory: 'new',
assigneeId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
assigneeEmail: 'sam@example.com',
teamId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'subject' => 'Export failing with 500',
'description' => 'Customer cannot export orders.',
'customer' => [
'email' => 'jane@example.com',
'name' => 'Jane Doe'
],
'statusId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'statusCategory' => 'new',
'assigneeId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'assigneeEmail' => 'sam@example.com',
'teamId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets"
payload := strings.NewReader("{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.chatbase.co/api/v2/agents/{agentId}/helpdesk/tickets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"subject\": \"Export failing with 500\",\n \"description\": \"Customer cannot export orders.\",\n \"customer\": {\n \"email\": \"jane@example.com\",\n \"name\": \"Jane Doe\"\n },\n \"statusId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"statusCategory\": \"new\",\n \"assigneeId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"assigneeEmail\": \"sam@example.com\",\n \"teamId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"ticketNumber": 123,
"subject": "<string>",
"description": "<string>",
"statusCategory": "on_customer",
"statusId": "<string>",
"assigneeId": "<string>",
"customer": {
"id": "<string>",
"name": "Ada Lovelace",
"email": "ada@example.com",
"phoneNumber": "<string>"
},
"metadata": {
"phone_number": "+1 525-525-5255"
},
"channel": "email",
"conversationId": "<string>",
"teamId": "<string>",
"createdAt": "2026-07-20T12:34:56.000Z",
"updatedAt": "2026-07-21T09:00:00.000Z",
"lastMessageAt": "2026-07-21T08:55:00.000Z"
}{
"error": {
"code": "VALIDATION_INVALID_BODY",
"message": "Invalid request"
}
}{
"error": {
"code": "AUTH_MISSING_API_KEY",
"message": "Authentication required"
}
}{
"error": {
"code": "SUBSCRIPTION_API_RESTRICTED_PLAN",
"message": "A Standard plan or higher is required to access the API"
}
}{
"error": {
"code": "AGENT_NOT_FOUND",
"message": "Agent not found"
}
}{
"error": {
"code": "TICKET_INVALID_STATUS",
"message": "The requested status could not be applied"
}
}{
"error": {
"code": "RATE_LIMIT_TOO_MANY_REQUESTS",
"message": "Too many requests, please try again later"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Something went wrong, please try again"
}
}Authorizations
API key from your account settings
Path Parameters
The agent ID
1"5QHA6VB-DIAbBhxwqxfdi"
Body
Ticket subject (1-500 characters)
1 - 500"Export failing with 500"
The first message body, written as a reply authored by the customer (1-10,000 characters)
1 - 10000"Customer cannot export orders."
Show child attributes
Show child attributes
ID of an existing status for this agent. Provide at most one of statusId / statusCategory.
Status category; resolves to that category's default status. Provide at most one of statusId / statusCategory. Defaults to the "new" category default when neither is provided.
new, on_you, on_customer, on_hold, closed, cancelled "new"
Platform user id of the agent to assign. Provide at most one of assigneeId / assigneeEmail. Pass null to explicitly create the ticket unassigned (suppresses auto-assignment); omit to let auto-assignment apply.
Email of the agent to assign (case-insensitive). Provide at most one of assigneeId / assigneeEmail.
"sam@example.com"
ID of an existing team for this agent. When provided without any assignee field, an agent is picked within this team using the team's own assignment strategy, and routing rules are skipped. When provided together with assigneeId/assigneeEmail, including assigneeId: null, no auto-assignment runs and the team is written as given.
Response
The created ticket
The ticket number
123
Ticket subject
Ticket description
Status category driving color/ordering semantics
new, on_you, on_customer, on_hold, closed, cancelled "on_customer"
ID of the ticket status. Resolve label/color via /ticket-statuses.
ID of the assigned agent user, or null when unassigned
Show child attributes
Show child attributes
Arbitrary extra fields captured on the ticket
Show child attributes
Show child attributes
{ "phone_number": "+1 525-525-5255" }
Channel the ticket originated from
helpdesk, iframe, email, whatsapp, api, messenger, instagram, center_stage, phone "email"
ID of the linked conversation, if any
ID of the assigned team, or null. Resolve via /teams.
ISO 8601 creation timestamp
"2026-07-20T12:34:56.000Z"
ISO 8601 timestamp of the last update
"2026-07-21T09:00:00.000Z"
ISO 8601 timestamp of the most recent message, or null if the ticket has no messages
"2026-07-21T08:55:00.000Z"
