Support tickets via API
POST /v1/tickets — open a support ticket, read the thread, follow up and close it with an API key: fields, attachments, statuses, limits and compatibility with /v1/technical-feedback.
The Tickets API is the single support channel: a ticket opened over the API shows up in the dashboard and vice versa. Authenticate with an API key (Authorization: Bearer or X-API-Key) or a dashboard session. You only ever see your own tickets.
Open a ticket
| Parameter | Type | Description |
|---|---|---|
subject | string | Required: 3 to 200 characters. |
message | string | Required: 10 to 8,000 characters. |
category | string | api_error, performance, incorrect_response, integration, feature_request, other, billing, account or general (default). |
requestIds | string[] | Optional, up to 10 request IDs from your account (the x-request-id response header). |
clientIncidentId | string | Optional stable series ID on your side: an open ticket with the same ID is reused. |
files | file[] | multipart/form-data only: up to 5 PNG, JPEG, GIF or WebP images, 10 MB each, 10 per ticket. |
curl https://getvibeapi.com/v1/tickets \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "Stream stops after 30 seconds",
"message": "stream=true on /v1/chat/completions stops after about 30 seconds; retrying does not help.",
"category": "api_error",
"requestIds": ["req_123"]
}'With a screenshot — multipart:
curl https://getvibeapi.com/v1/tickets \
-H "Authorization: Bearer $API_KEY" \
-F subject="Wrong response" \
-F message="The model returns an empty answer, screenshot attached." \
-F category=incorrect_response \
-F [email protected]Response
{
"deduplicated": false,
"ticket": {
"id": "cmg1abc234",
"object": "ticket",
"subject": "Stream stops after 30 seconds",
"category": "api_error",
"source": "api",
"status": "open",
"requestIds": ["req_123"],
"clientIncidentId": null,
"occurrences": 1,
"createdAt": "2026-09-27T09:14:00.000Z",
"updatedAt": "2026-09-27T09:14:00.000Z",
"repliedAt": null
}
}A new ticket returns 201. If the same open ticket already exists (same category, subject, message and requestIds, or the same clientIncidentId), that ticket is returned with deduplicated: true, status 200 and a higher occurrences.
List tickets
Newest first. Response: { "object": "list", "data": [...], "hasMore": true, "nextCursor": "..." }. Next page: ?after=<nextCursor>. limit is 1 to 100.
Thread and status
curl https://getvibeapi.com/v1/tickets/cmg1abc234 \
-H "Authorization: Bearer $API_KEY"ticket.messages holds your messages (author: "client") and support replies (author: "staff") in time order. Download attachments with GET /v1/tickets/{id}/attachments/{attachmentId}. A foreign or unknown ID returns 404.
Follow up and close
curl https://getvibeapi.com/v1/tickets/cmg1abc234/messages \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"message": "It happened again today at 10:05 UTC, request id req_456."}'A message (up to 8,000 characters, multipart with files allowed) reopens a replied ticket. A closed ticket cannot take messages — it returns 409; open a new one. Closing is idempotent.
Statuses
| Parameter | Type | Description |
|---|---|---|
open | status | Waiting for support. |
replied | status | Support replied; your next message sets it back to open. |
closed | status | Closed by you or by support. |
Limits and errors
Per account: 10 new tickets per hour and 60 messages per hour; beyond that 429 with a Retry-After header. Errors: { "error": "…", "code": "invalid_fields" } — codes invalid_fields, invalid_request_ids, too_many_attachments, file_too_large (413), unsupported_attachment (415), not_found (404), ticket_closed (409), rate_limited (429).
Security
Compatibility: /v1/technical-feedback
POST /v1/technical-feedback and GET /v1/technical-feedback/{id} keep working with the same fields (category, summary, details, requestIds, clientIncidentId) and the { "deduplicated", "incident" } response. Such a report is stored as a ticket (source: "technical-feedback") and appears in GET /v1/tickets. Requests to change balance, access or deployments are still rejected there with 422. New integrations should use /v1/tickets.