Ticket APIs
Use the ticket APIs to create support tickets from external systems and retrieve or export tickets for reporting, reconciliation, or operational workflows.
Authentication
Create an access token from Settings -> Integrations in the Flowcall dashboard.
Pass the token as a Bearer token in every request:
Authorization: Bearer <your_access_token>
Create a Manual Ticket
Creates a new support ticket with customer details and the customer's query.
POST https://api.flowcall.co/apis/tickets/manual
Rate Limits
| Window | Limit |
|---|---|
| Per minute | 5 requests |
| Per hour | 200 requests |
| Per day | 1000 requests |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
customer | object | Yes | Customer information. See Customer Object. |
orderName | string | No | Order name or order number associated with the ticket. |
subject | string | No | Short summary or title for the ticket. |
query | string | Yes | Customer question or issue description. Either subject or query must be provided. |
payload | string | No | Additional context as a JSON string, for example "{\"key\":\"value\"}". |
payloadFormat | string | No | Identifier for the payload structure. Use a unique name for each distinct payload shape. |
source | string | No | Built-in ticket source, or a manual-source label. See Manual Source Labels. |
manualSourceLabel | string | No | Optional configured label when source is manual, such as Store or POS. |
currentTaskId | string | No | Workflow task ID to route the ticket to. Takes precedence over taskName. |
taskName | string | No | Workflow task name to route the ticket to. It is looked up by name within the account. |
objectiveValues | object | No | Values for normal task objectives, keyed by objective parameter. |
dataPointOverrides | object | No | Request-scoped string values that replace referenced read-only data points for this task execution. |
relatedTicketNumber | string | No | Ticket number of a related or previous ticket. |
waitForTicket | boolean | No | Defaults to true: the ticket is created and returned. Send false to only find or create the customer. |
forceCreateTicket | boolean | No | Defaults to false: an open ticket for the same customer and task is reused. Send true to always create a new ticket. |
fastResponse | boolean | No | If true, skips AI processing of subject/query and returns as soon as the ticket is created. |
skipExecuteAction | boolean | No | If true, Flowcall skips configured execution actions. Defaults to true when overrides are sent. |
images | string[] | No | Image URLs related to the ticket. |
Customer Object
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Customer full name. |
phone | string | Yes* | Customer phone number. |
email | string | Yes* | Customer email address. |
shopifyCustomerId | string | No | Shopify customer ID, if applicable. |
*Either phone or email is required.
Manual Source Labels
The built-in source values are whatsapp, email, liveChat, instagram,
voiceCall, and manual.
Accounts can configure additional labels for manually created tickets, such as
Store or POS, in Settings → Ticketing → Manual Ticket Sources. You can
send one of these labels directly in source:
{
"source": "POS"
}
Flowcall stores this as:
{
"source": "manual",
"manualSourceLabel": "POS"
}
Configured labels are matched case-insensitively and stored using their
configured casing. Any non-empty source value that is not a built-in source is
also normalized to source: "manual" and retained in manualSourceLabel, even
when it has not been configured yet.
Alternatively, send the fields explicitly:
{
"source": "manual",
"manualSourceLabel": "Store"
}
Data Point Overrides
Use dataPointOverrides when a manually created ticket must evaluate a task
with an explicit value instead of reading that value from its normal data
source. Overrides apply only to this request; they do not update the customer,
order, Google Sheet, or custom integration that normally supplies the data.
A task must be selected with taskName (or currentTaskId). Each override key
must be a data point directly referenced by that task, and values must be
non-empty strings. Keys are matched case-insensitively to the task's canonical
data point names. A request can contain at most 50 overrides.
The API rejects an override when:
- the data point is unknown or is not directly used by the selected task;
- it represents a computed or execute-action objective;
- it writes to a Google Sheet;
- its value is outside the data point's configured
possibleValues; or - the same key (matched case-insensitively) is also present in
objectiveValues.
The overridden value is used by dependent objectives and task transitions. To
reduce unintended side effects, execution actions are skipped by default when
dataPointOverrides is present. Set skipExecuteAction to false explicitly
only when those actions should run with the overridden inputs.
For example:
{
"taskName": "Return order",
"objectiveValues": {
"returnReason": "Wrong size"
},
"dataPointOverrides": {
"orderStatus": "delivered"
},
"fastResponse": true
}
Example Request
curl -X POST https://api.flowcall.co/apis/tickets/manual \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"name": "John Doe",
"phone": "911234567890",
"email": "john@example.com"
},
"orderName": "#1042",
"subject": "Return request - wrong size",
"query": "I want to return my order, the size does not fit.",
"taskName": "Return order",
"objectiveValues": {
"returnReason": "Wrong size"
},
"dataPointOverrides": {
"orderStatus": "delivered"
},
"payload": "{\"source\":\"ivr\",\"priority\":\"high\"}",
"payloadFormat": "ivr_return_v1",
"source": "voiceCall",
"relatedTicketNumber": "TKT-2048",
"fastResponse": true,
"skipExecuteAction": true,
"images": [
"https://cdn.example.com/images/damaged-item-1.jpg",
"https://cdn.example.com/images/damaged-item-2.jpg"
]
}'
Success Response
{
"success": true,
"customer": {
"id": "cust_abc123",
"name": "John Doe",
"phone": "+1234567890",
"email": "john@example.com"
},
"ticketId": "64f7b2c1c9d2a4e7b1f3a9d0",
"existingTicket": false,
"ticket": { "id": "64f7b2c1c9d2a4e7b1f3a9d0", "...": "..." }
}
existingTicket is true when an open ticket for the same customer and task was reused.
When waitForTicket is false, no ticket is created and the response includes requestId instead of ticketId:
{
"success": true,
"customer": {
"id": "cust_abc123",
"name": "John Doe",
"phone": "+1234567890",
"email": "john@example.com"
},
"requestId": "64f7b2c1c9d2a4e7b1f3a9d0"
}
Error Responses
| Status | Body | Cause |
|---|---|---|
400 | { "error": "phone or email is required" } | Missing customer.phone and customer.email. |
400 | { "error": "Data point ..." } | Invalid or unsafe dataPointOverrides input. |
403 | { "error": "Not authorized" } | Invalid or missing Bearer token. |
429 | Rate limit error | Rate limit exceeded. |
List Tickets
Retrieves a paginated list of tickets with filtering, sorting, and search.
POST https://api.flowcall.co/apis/task-runs/tickets/list
Request Body
All fields are optional unless noted otherwise.
Pagination And Sorting
| Field | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number for pagination. |
limit | number | 10 | Number of results per page. Maximum 250. |
sortOrder | "asc" or "desc" | "desc" | Sort direction based on the timestamp column selected by timestampKey. |
timestampKey | string | createdAt | Column to sort and filter by date. Accepted values are createdAt, updatedAt, resolvedAt, executedAt, and assignedAt. |
Date Filters
| Field | Type | Description |
|---|---|---|
startDate | string | ISO 8601 date string. Filters tickets on or after this date based on timestampKey. |
endDate | string | ISO 8601 date string. Filters tickets on or before this date based on timestampKey. |
ignoreDateRange | boolean | If true, skips date range filtering. Only allowed when filtering by assigned or queued statuses. |
Status And Assignment Filters
| Field | Type | Description |
|---|---|---|
statuses | string[] | Filter by ticket statuses, for example ["open", "assigned", "resolved"]. |
excludeInProgress | boolean | Exclude tickets with in_progress status. |
agentId | string | Filter by assigned agent ID. |
involvedAgentId | string | Filter tickets where this agent was involved. |
agentInvolvement | "only_ai" or "agents_involved" | Filter by whether human agents were involved. |
unassigned | boolean | Filter for unassigned tickets only. |
createdByUserId | string | Filter by the user who created the ticket. |
Task And Team Filters
| Field | Type | Description |
|---|---|---|
taskIds | string[] | Filter by specific task IDs. |
noTaskIds | boolean | Filter for tickets with no associated task. |
taskTeamIds | string[] | Filter by task team IDs. |
Search And Lookup Filters
| Field | Type | Description |
|---|---|---|
search | string | Search ticket summary, order name, ticket name or number, customer name, email, and phone. |
phoneNumber | string | Filter by customer phone number. Supports comma-separated values. |
orderName | string | Filter by order name. Supports comma-separated values. |
ticketNumber | string | Filter by exact ticket name or number. Supports comma-separated values. |
source | string | Filter by ticket source. |
manualSourceLabel | string | Filter manual tickets by their exact manual-source label. When provided without source, source: "manual" is implied. |
Classification And Other Filters
| Field | Type | Description |
|---|---|---|
category | string | Filter by disposition category. |
subcategory | string | Filter by disposition subcategory. |
sentiments | string[] | Filter by customer sentiments. Matches any value in the array. |
excludeChildTickets | boolean | Exclude child tickets. |
parentTicketId | string | Filter child tickets belonging to this parent ticket ID. |
Example Request
curl -X POST https://api.flowcall.co/apis/task-runs/tickets/list \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"limit": 20,
"startDate": "2026-03-01T00:00:00.000Z",
"endDate": "2026-03-18T23:59:59.999Z",
"statuses": ["open", "assigned"],
"sortOrder": "desc"
}'
Success Response
{
"data": [
{
"id": "ticket-id",
"ticketNumber": 1234,
"status": "assigned",
"summary": "Customer inquiry about order",
"orderName": "#1001",
"source": "whatsapp",
"manualSourceLabel": null,
"customerId": "customer-id",
"assignedToId": "agent-id",
"taskId": "task-id",
"createdAt": "2026-03-15T10:00:00.000Z",
"resolvedAt": null,
"csat": {
"rating": 5,
"comment": "Great support!"
}
}
],
"total": 150,
"page": 1,
"limit": 20,
"totalPages": 8
}
Error Responses
| Status | Message |
|---|---|
400 | Limit cannot be greater than 250 |
400 | Invalid date range or status combination |
500 | Internal server error |
Export Tickets as CSV
Ticket CSV exports run asynchronously. Starting an export returns a job ID immediately; use that ID to check progress and retrieve a short-lived download URL when the CSV is ready.
Start an Export
POST https://api.flowcall.co/apis/task-runs/tickets/export
Request Body
The export endpoint accepts the same filters and sorting fields as
List Tickets. Pagination fields such as page and limit are
not required because every matching ticket is exported.
The following optional fields control how timestamps are displayed in the CSV:
| Field | Type | Default | Description |
|---|---|---|---|
timezone | string | Business timezone, then Asia/Kolkata | IANA timezone name, for example Asia/Kolkata or America/New_York. |
locale | string | en-US | Unicode locale identifier used to format local timestamp strings, for example en-IN. |
timestampFormat | string | display | Timestamp format: display (DD-MM-YY HH:MM:SS), legacy (locale-sensitive), or iso (ISO 8601 with offset). |
When both startDate and endDate are provided, the export date range cannot
exceed 92 days. Dates are filtered using timestampKey, in the same way as the
list endpoint.
Example Request
curl -X POST https://api.flowcall.co/apis/task-runs/tickets/export \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-03-01T00:00:00.000Z",
"endDate": "2026-03-18T23:59:59.999Z",
"timestampKey": "createdAt",
"statuses": ["open", "assigned", "resolved"],
"sortOrder": "desc",
"timezone": "Asia/Kolkata",
"locale": "en-IN"
}'
Success Response
The endpoint returns HTTP 202 Accepted after the job has been queued:
{
"success": true,
"jobId": "8ce98fc2-8a5a-4ab1-b42c-00c09a0526a7",
"status": "queued",
"total": 1499,
"fileName": "tickets-2026-03-01_to_2026-03-18.csv",
"statusUrl": "/apis/task-runs/tickets/export/8ce98fc2-8a5a-4ab1-b42c-00c09a0526a7"
}
Check Export Status and Download
Poll the returned statusUrl using the same Bearer token:
GET https://api.flowcall.co/apis/task-runs/tickets/export/{jobId}
curl https://api.flowcall.co/apis/task-runs/tickets/export/8ce98fc2-8a5a-4ab1-b42c-00c09a0526a7 \
-H "Authorization: Bearer <your_access_token>"
The job status is one of queued, running, succeeded, or failed. While
the export is being generated, the response contains progress information:
{
"success": true,
"job": {
"jobId": "8ce98fc2-8a5a-4ab1-b42c-00c09a0526a7",
"status": "running",
"total": 1499,
"processed": 800,
"fileName": "tickets-2026-03-01_to_2026-03-18.csv",
"createdAt": "2026-03-19T05:30:00.000Z",
"startedAt": "2026-03-19T05:30:02.000Z",
"updatedAt": "2026-03-19T05:30:08.000Z"
}
}
When job.status is succeeded, the response includes the download URL:
{
"success": true,
"job": {
"jobId": "8ce98fc2-8a5a-4ab1-b42c-00c09a0526a7",
"status": "succeeded",
"total": 1499,
"processed": 1499,
"fileName": "tickets-2026-03-01_to_2026-03-18.csv",
"fileSizeBytes": 3223018,
"createdAt": "2026-03-19T05:30:00.000Z",
"startedAt": "2026-03-19T05:30:02.000Z",
"completedAt": "2026-03-19T05:30:14.000Z",
"availableUntil": "2026-03-20T05:30:14.000Z",
"updatedAt": "2026-03-19T05:30:14.000Z"
},
"downloadUrl": "https://storage.googleapis.com/...",
"expiresAt": "2026-03-19T05:45:15.000Z",
"downloadExpired": false
}
Download the CSV directly from downloadUrl. The generated file is retained
for 24 hours. Each signed URL is valid for 15 minutes; call the status endpoint
again to obtain a fresh URL while the file is still retained. When the job is
failed, the job.error field contains a safe error message.
If no timezone is supplied when starting the export, the API uses the account's
business timezone. If that is missing or invalid, it uses Asia/Kolkata.
CSV Columns
The export contains the same operational values used by the Tickets dashboard, organized into these column groups:
| Group | Columns |
|---|---|
| Ticket | Ticket Number, Ticket Type, Child Ticket Param, Task Names, Team, Actions, Status, Source, Sentiments, Order Name, Summary, Resolution |
| Assignment | Assigned To, Assigned By, Assigned At, Involved Sources, Involved Agents, Has Involved Agent, Resolved By |
| Customer | Customer Name, Customer Phone, Customer Email, Customer ID, Chat Link |
| Timing | Created At, Queued Time, First Response Timestamp, Response Time, First Response Time (minutes), Total Response Time (minutes), Latest Response Time, Age, Resolution Time, Last Updated At, Executed At, Resolved At |
| Related work | Child Tickets, Interaction Tickets, Chat Interactions, Email Threads, Customer Email Messages, Agent Email Messages, Incoming Calls, Outgoing Calls, Voice Calls, FCR, Voice FCR, Voice FCR Reason, Voice FCR Evaluated At, Email ThreadId, Email Client, Auto Resolved |
| SLA | One SLA: <label> column for every SLA configuration. Duplicate labels receive a numeric suffix. |
| Task objectives | One Objective: <param> column for every objective parameter configured on the tasks included in the filtered result. |
| Other payload data | Additional Data, containing a JSON object of payload keys that are not task objectives, summary, or emailClient. |
| CSAT | CSAT Status, CSAT Rating, CSAT Comment, CSAT Sent At, CSAT Submitted At |
| Disposition | Category, Subcategory, plus one Disposition: <label> column for every active disposition field, including category fields. |
Local ticket timestamp columns are formatted using the resolved locale and
timezone. CSAT Sent At and CSAT Submitted At remain ISO 8601 timestamps.
Response Time measures ticket creation to first response. Resolution Time
measures ticket creation to resolution; both use HH:MM durations. When
opening hours are configured for a ticket's account, both durations count
only configured opening hours and exclude closed days and configured holidays;
otherwise they use ordinary elapsed time. First Response Time (minutes) uses
the same business-hours-aware duration as Response Time.
For manual tickets, the CSV Source column contains manualSourceLabel when
present; otherwise it contains Manual.
Customer Email Messages counts distinct messages in the ticket family's linked
email threads that were sent by addresses outside the configured mailboxes.
Agent Email Messages counts distinct messages sent from configured mailbox owner
or alias addresses, excluding messages tagged as AI- or system-generated. These
family metrics are populated on parent ticket rows and left blank on child and
interaction-ticket rows.
Chat Interactions counts distinct chat sessions across the ticket family.
Voice Calls is the sum of Incoming Calls and Outgoing Calls.
Legacy FCR calculation
FCR means First Contact Resolution. It is calculated from the lifetime activity
of the complete ticket family and is populated only on the parent ticket row. Child
and interaction-ticket rows have a blank FCR value.
| Export value | Calculation |
|---|---|
Yes | The parent is in closed, stale, stale_marked_automatically, resolved_by_agent, or resolved_by_ai; the family has no more than one customer-contact channel; and every applicable channel rule passes. Voice requires exactly one incoming call. Email requires one or two customer emails and at most one human-agent email message. |
No | The family has a customer email or incoming-voice contact but the parent is not terminal, the voice or email rule fails, or the family has more than one customer-contact channel. A multi-channel family is No even when each individual channel rule passes. |
| Blank | The row is a child or interaction ticket, or the parent family has neither a customer email nor an incoming call. A family with only one unsupported FCR channel, such as chat, also remains blank. |
The email rule counts distinct messages sent from configured mailbox owner or alias
addresses. AI- and system-generated messages are excluded. Customer email establishes
email as a contact channel, and more than two customer emails makes FCR No.
Agent-originated email without a customer email does not add a second channel, so
an agent can send a confirmation email during a qualifying voice call without making
FCR No. The voice rule counts incoming calls only; outgoing calls do not affect FCR.
Channel count comes from the family's interaction sources, with email included only
when the family contains a customer-originated email and voice included only when it
contains an incoming call. manual is added as a synthetic channel when it appears as
the current or an involved source because manual tickets do not create interaction
rows.
Stored voice FCR
Voice FCR is the evidence-backed value persisted on the customer-facing root
ticket when an incoming call is evaluated. It is separate from the legacy FCR
calculation so existing exports and integrations retain their current meaning.
| Export value | Meaning |
|---|---|
Yes | Transcript analysis confirmed resolved_on_call, the root family passed its final protection checks, and the family was resolved. |
No | The call was evaluated as unresolved, follow-up was delegated, resolution occurred without usable evaluation evidence, or a later inbound customer contact was linked to the same family. |
Unknown | The root has an incoming call but no stored decision, including legacy tickets that were not backfilled. |
| Blank | The row is a child or interaction ticket, or the root has no incoming voice call. |
Voice FCR Reason contains the stored machine-readable reason and
Voice FCR Evaluated At contains the decision timestamp. A frontend child that is created
and immediately auto-closed with the root does not by itself disqualify FCR.
Protected or delegated child work does. Outbound calls and agent-only confirmation
emails do not invalidate the value; a later customer-originated message or a
different incoming call linked to the family does.
The set of task-objective, SLA, and disposition columns depends on the account
configuration and on the tasks included by the export filters. Unknown payload
keys do not create additional CSV columns; they are serialized into
Additional Data instead.
Related-work counts are lifetime totals for the complete ticket family and are populated only on parent-ticket rows. Email thread counts include every email provider represented in the ticket interaction history.
Error Responses
| Status | Message |
|---|---|
400 | Invalid startDate or endDate |
400 | endDate must be after startDate |
400 | Export is limited to a maximum date range of 92 days |
400 | Invalid export locale or timezone |
404 | Ticket export job not found |
429 | Rate limit exceeded. The ticket list and export endpoints allow 200 requests per hour per access token. |
500 | Failed to enqueue or fetch the ticket export |