# Kustomer API: Frequently Asked Questions

>  Kustomer API Frequently Asked Questions     This article answers common questions about using the Kustomer REST API based on the most frequent topics raised

Source: https://help.kustomer.com/en_us/kustomer-api-frequently-asked-questions-rJPDs3yAZg

Last updated: 2026-08-07T14:59:12.293Z

This article answers common questions about using the Kustomer REST API. Whether you're building an integration, automating workflows, or pulling data for reporting, you'll find step-by-step answers to the questions below.

**Who can access this feature?**

Users with API access and an active Kustomer API key. Some endpoints require \`org.admin\` or specific role permissions.

* * *

### 1\. How do I search for conversations via the API?

Kustomer does not have a standalone \`/v1/conversations/search\` endpoint. To search for conversations, use the **Customer Search** endpoint with the \`queryContext\` parameter set to \`"conversation"\`.

**Endpoint:** \`POST /v1/customers/search\`

**Key requirement:** When \`queryContext\` is set to \`"conversation"\`, all filter field names must be prefixed with \`conversation\_\`. For example, use \`conversation\_created\_at\` instead of \`createdAt\`, and \`conversation\_assigned\_teams\` instead of \`assignedTeams\`.

**Example — Find conversations by date range, team, and channel:**

\`\`\`json

{

  "and": \[

    {"conversation\_created\_at": {"gte": "2026-03-01T00:00:00.000Z"}},

    {"conversation\_created\_at": {"lte": "2026-03-31T23:59:59.999Z"}},

    {"conversation\_assigned\_teams": {"in": \["TEAM\_ID\_1", "TEAM\_ID\_2"\]}},

    {"conversation\_direction": {"equals": "in"}},

    {"conversation\_channels": {"in": \["email", "sms"\]}}

  \],

  "queryContext": "conversation",

  "timeZone": "GMT"

}

\`\`\`

**Example — Exclude conversations with specific tags:**

\`\`\`json

{

  "and": \[

    {"conversation\_tags": {"not\_in": \["TAG\_ID\_1", "TAG\_ID\_2"\]}}

  \],

  "queryContext": "conversation",

  "timeZone": "America/Los\_Angeles"

}

\`\`\`

**Note:** Tags are stored as IDs in the API. You can retrieve tag IDs from the Kustomer UI or via the Tags API.

* * *

### 2\. Why is the Search API missing records? What are the data limits?

There are two key limits to be aware of when using the Search API.

#### **2-year data limit**

The Search API (\`POST /v1/customers/search\`) only returns records that were **updated within the past 2 years**. Records older than 2 years will not appear in search results.

**To access records older than 2 years,** use the Archive Search endpoint instead:

**Endpoint:** \`POST /v1/customers/archive/search\`

This endpoint accepts the same query format as the standard Search endpoint. It can return both archived records and recently updated records — it is not limited to only old data.

####   
100-page pagination limit

The Search API has a hard limit of **100 pages per query**. If your dataset exceeds 100 pages, use cursor-based pagination to work around this limit.

**How cursor-based pagination works:**

1\. Sort your results by \`conversation\_updated\_at\` in ascending order.

2\. After processing a batch, take the \`updated\_at\` value from the last record in the response.

3\. Use that value as the \`gte\` starting point in your next request.

**Example — Cursor-based pagination:**

\`\`\`json

{

  "and": \[

    {"conversation\_updated\_at": {"gte": "2024-11-20T16:34:00.000Z"}}

  \],

  "queryContext": "conversation",

  "sort": \[{"conversation\_updated\_at": "asc"}\]

}

\`\`\`

Repeat this pattern, advancing the \`gte\` timestamp with each batch, until you've retrieved all records.

* * *

### 3\. How do I send an Instagram DM via the API?

To send an Instagram DM through the Kustomer API, you must **reply to an existing Instagram conversation**. Instagram does not support initiating new conversations via API — you can only respond to messages a customer has already sent to your Instagram account.

**Prerequisites:**

\- The customer must have an existing Instagram conversation on their timeline

\- Your Instagram integration must be active and connected in Kustomer

\- The \`from\` value must be your organization's Instagram Page ID

\- The \`to\` value must be the customer's Instagram-scoped user ID (IGSID)

**Endpoint:** \`POST /v1/customers/{customerId}/drafts\`

**Example request body:**

\`\`\`json

{

  "channel": "instagram",

  "from": "YOUR\_IG\_PAGE\_ID",

  "to": "CUSTOMER\_IGSID",

  "body": "Your message text here",

  "conversation": "EXISTING\_CONVERSATION\_ID"

}

\`\`\`

**Note:** Do not include the \`sendAt\` parameter if you want the message sent immediately. Including \`sendAt\` schedules the message for a future time, which may not dispatch correctly for Instagram.

**Tip:** If your draft is created with status \`"scheduled"\` but the message is never delivered, verify that the \`conversation\` ID references an active Instagram conversation and that your Instagram integration is properly connected.

This same pattern applies to other social channels — for Facebook Messenger and WhatsApp, you must also reply within an existing conversation thread rather than initiating a new one.

* * *

### 4\. How do I pin a conversation via the API?

You can pin or unpin a conversation on a customer's timeline using the Update Conversation endpoint.

**Endpoint:** \`PATCH /v1/conversations/{conversationId}\`

**Pin a conversation:**

\`\`\`json

{

  "pinned": true

}

\`\`\`

**Unpin a conversation:**

\`\`\`json

{

  "pinned": false

}

\`\`\`

**Tip:** This can also be used inside a Kustomer Workflow via a REST API step to automatically pin conversations that meet certain criteria — for example, pinning any conversation tagged "VIP" when it is created.

* * *

### 5\. How do I see which Shortcuts were used in a conversation via the API?

Shortcut usage data is stored on the **message** object, not the conversation object. There are two ways to access it.

#### **Option 1 — Get full shortcut details for a specific message:**

**Endpoint:** \`GET /v1/messages/{messageId}/shortcuts\`

This returns the complete shortcut object, including the shortcut name, body text, and metadata.

#### **Option 2 — Get shortcut IDs from all messages in a conversation:**

**Endpoint:** \`GET /v1/conversations/{conversationId}/messages\`

Each message in the response includes a \`shortcuts\` relationship field that contains the shortcut ID if one was used. However, this only returns the ID — not the shortcut name or content. To retrieve the full details, you would need to use the endpoint in Option 1 for each message.

**Note:** There is no single endpoint to retrieve all shortcuts used across multiple conversations. To build shortcut usage reports at scale, consider configuring your Shortcuts to apply a unique tag to conversations when used. This allows you to report on shortcut usage through conversation tags in Kustomer reporting.

* * *

### 6\. How do I update a Business Rule via the API?

You can update an existing Business Rule using the following endpoint.

**Endpoint:** \`PUT /v1/business-rules/{ruleId}\`

To find a rule's ID, first retrieve a list of all Business Rules:

**Endpoint:** \`GET /v1/business-rules\`

This returns all rules in your organization, including their IDs. Use the ID of the rule you want to update in the \`PUT\` request.

**Note:** This endpoint requires an API key with \`org.admin\` or equivalent permissions.

* * *

### 7\. Which rate limit headers does the API return?

Kustomer API responses include the following rate limit headers across **all applicable endpoints** — they are not specific to the Search API.

| Header | Description |

|--------|-------------|

| \`x-ratelimit-limit\` | The maximum number of requests allowed in the current window |

| \`x-ratelimit-remaining\` | The number of requests remaining in the current window |

| \`x-ratelimit-route-remaining\` | The number of requests remaining for the specific route or endpoint |

You can use these headers to monitor your usage in real time and build retry logic that backs off before hitting the limit. For example, if \`x-ratelimit-remaining\` drops to a low value, pause your requests before continuing.

**\>Note:** API requests cannot exceed 2,000 requests per minute (1,000 for Enterprise plans). Additionally, update requests to the same object (customer, conversation, company, custom object, or message) cannot exceed 50 requests per 10-minute window.

* * *

### **8\. How do I see which workflows ran on a conversation?**

To identify which workflows executed on a specific conversation, use the Conversation Events endpoint.

**Endpoint:** \`GET /v1/conversations/{conversationId}/events\`

Workflow-triggered events have a \`client\` field set to \`"workflow"\`. This lets you distinguish automated actions from those performed by agents, API calls, or system processes.

**Filtering for workflow events:**

The endpoint returns all conversation events — not just workflow events. After retrieving results, filter client-side for entries where \`"client": "workflow"\`. Each matching event includes:

\- The type of action taken (e.g., status change, tag applied, assignment update)

\- The timestamp when the workflow ran

\- Details about what changed

**Tip:** Use this endpoint in combination with Workflow debug logs in Settings > Platform > Workflows for a complete picture of how and when a workflow ran on a specific conversation.

* * *

### **9\. How do I send an outbound email via the API?**

Sending an outbound email through the Kustomer API is a two-step process: first create a draft, then send it.

**Step 1 — Create a draft:**

**Endpoint:** \`POST /v1/customers/{customerId}/drafts\`

\`\`\`json

{

  "channel": "email",

  "direction": "out",

  "app": "email",

  "subject": "Your Subject Line",

  "body": "Your email body content here",

  "to": "[recipient@example.com](mailto:recipient@example.com)"

}

\`\`\`

The response will include a \`draftId\`.

**Step 2 — Send the draft:**

**Endpoint:** \`PUT /v1/customers/{customerId}/drafts/{draftId}\`

Include \`"sendAt"\` set to the current timestamp to send immediately. Omitting \`sendAt\` or leaving it blank may leave the message as a draft.

\`\`\`json

{

  "sendAt": "2026-04-29T15:00:00.000Z"

}

\`\`\`

**Note:** Ensure your environment has an active email integration configured. In sandbox environments, verify that your email integration is set up and that your API key has the correct permissions for sending messages.

**Tip:** The same Drafts API pattern applies to SMS and other messaging channels — change the \`channel\` and \`app\` values accordingly.

* * *

### **10\. Why isn't the Outbound Message Count incrementing for API messages?**

The \`outbound\_message\_count\` field on conversations does **no**t increment for outbound chat messages created through API integrations. This is a known limitation.

The count currently only reflects messages sent through the Kustomer UI or SDK. Email and other channel messages sent through the standard Drafts API flow are counted correctly.

If you need to track outbound API message volume, consider using the Conversation Events endpoint (\`GET /v1/conversations/{conversationId}/events\`) to identify API-created messages, or configuring a Workflow to tag conversations when an outbound API message is sent.

* * *

### **11\. How do I update a user's work session status via the API?**

You can change a user's availability status programmatically using the Work Session endpoint.

**Endpoint:** \`PUT /v1/users/{userId}/work-session\`

This is useful in scenarios where you want to automatically update agent availability based on conversation events. For example, you can use this endpoint inside a Workflow via a REST API step to change a user's status when they mark a conversation as done.

**Tip:** To find a user's ID, use \`GET /v1/users\` to list all users in your organization, or retrieve a specific user with \`GET /v1/users/{userId}\`.

* * *

### **12\. How do I perform bulk operations (close, delete, update) via the API?**

Kustomer does not have a dedicated bulk operation endpoint for conversations or customers. To perform bulk updates, combine the Search API with individual update calls.

**General approach:**

1\. **Search for your target records** using the Search API:

   **Endpoint:** \`POST /v1/customers/search\`

   Build a query that returns exactly the records you want to update. Use the \`queryContext\` parameter to target conversations, customers, or other objects.

2\. **Iterate through results** and update each record using the appropriate endpoint. For example, to close conversations:

   **Endpoint:** \`PATCH /v1/conversations/{conversationId}\`

   \`\`\`json

   {

     "status": "done"

   }

   \`\`\`

**Rate limit considerations for bulk operations:**

1.  Check the \`x-ratelimit-remaining\` and \`x-ratelimit-route-remaining\` response headers on each request.
2.  Implement a delay or backoff between requests when \`x-ratelimit-remaining\` drops low.
3.  Remember: update requests to the **same object** are limited to 50 requests per 10-minute window across all methods (API calls, workflows, business rules, and agent actions combined).
4.  For large-scale bulk operations, contact \[Kustomer Support\]([https://help.kustomer.com](https://help.kustomer.com)) to discuss a temporary rate limit adjustment.

  

**Note:** When paginating through large result sets with the Search API, keep the 100-page limit in mind. Use cursor-based pagination (see \[Question 2\](#2-why-is-the-search-api-missing-records-what-are-the-data-limits)) to iterate through datasets larger than 100 pages.

* * *

### 13\. How do I search conversations by Date Range

**Action**

**Endpoint**

**Required Permission**

Search conversations by date range

`POST /v1/customers/search` (with `queryContext: "conversation"`)

`org.user.search.read`

  

**Searching Conversations via the API**

To search conversations, use the **Customer Search endpoint** with `queryContext` set to `"conversation"`. There is no standalone `/v1/conversations/search` endpoint — requests to that path will return a 404.

**Endpoint:** `POST /v1/customers/search`  
**Required permission:** `org.user.search.read`

Example request body — conversations created in a date range:

```











{  "queryContext": "conversation",  "and": [    {      "createdAt": {        "$gte": "2026-05-01T00:00:00.000Z",        "$lte": "2026-05-04T23:59:59.999Z"      }    }  ]}
```

You can add additional filters to the `and` array. Use `GET /v1/customers/search/fields?queryContext=conversation` to retrieve all searchable conversation fields.

* * *

### **14\. Delete a note from a conversation**

You cannot delete notes directly from the Kustomer UI. To remove a note, use the Kustomer API.

To delete a note using the API:

1.  From the conversation timeline, locate the note you want to delete. Right-click on the note and select **Inspect** to find the note ID, or use the List Notes API endpoint to retrieve all notes on a conversation.
2.  Send a `DELETE` request to the following endpoint: `DELETE /v1/customers/{customerId}/notes/{noteId}`
3.  Verify that the note no longer appears in the conversation timeline.

Deleting a note removes only that individual note. It does not delete the conversation or any other messages on the timeline.

* * *

### **15\. Retrieve user deactivation data**

Kustomer does not include user data (such as deactivation timestamps) in standard reports. To retrieve this information, use the Kustomer API.

To find when a user was deactivated, send a `GET` request to:

`GET /v1/users/{userId}`

The response includes a `deactivatedAt` timestamp if the user has been deactivated. To retrieve all users, send a `GET` request to `/v1/users` and filter by status.

* * *

### 16\. Troubleshoot common API errors

#### **429 — Too many requests**

A `429` response means your application has exceeded the Kustomer API rate limit. Kustomer applies rate limits to protect platform stability.

**Common causes:**

*   Sending a high volume of API requests in a short period, for example during bulk data imports or load testing.
*   A misconfigured retry loop that resends failed requests without a delay.

**What to do:**

*   Add exponential backoff to your integration. When you receive a `429`, wait before retrying. Double the wait time with each subsequent retry.
*   Reduce the frequency of API calls by batching requests where the API supports it.

#### **504 — Gateway timeout**

A `504` response means the Kustomer server did not return a response within the allowed time window. This typically occurs when a single API request involves a very large payload or a complex query.

**Common causes:**

*   Attempting to retrieve or write a very large number of records in a single API call.
*   Complex search queries on large datasets.

**What to do:**

*   Paginate your requests. Use the `page` and `pageSize` parameters to retrieve records in smaller batches rather than attempting to pull all records at once.
*   If the timeout is intermittent and not tied to large payloads, it may indicate a platform issue. Check the [Kustomer status page](https://status.kustomer.com) for any active incidents, then contact support if the issue persists.

* * *

### 17\. Bulk Close Tasks

Kustomer does not currently support bulk closing tasks through the user interface. To bulk update task statuses, use the Kustomer API.

#### **In this article**

*   Retrieve open tasks
*   Update task statuses

#### **Retrieve open tasks**

To get a list of tasks that need to be closed, call the **Get KObjects** endpoint and filter for tasks that do not have a status of "Done."

#### **Update task statuses**

For each task that you want to close, call the **Update KObject** endpoint and set the task status to `done`.

**Note:** The API processes one request at a time. Review the [API rate limits](https://help.kustomer.com/api-rate-limits-Sk2xoQgYX) to avoid exceeding your organization's request limits when updating a large number of tasks.

* * *

### 18\. Assign a conversation to a queue using the work items API

Use the Kustomer Routing API to programmatically assign conversations to queues by creating work items. This is useful when external systems need to route conversations without relying on business rules.

### **Prerequisites**

*   An API token with `org.user.workitem.write` permission
*   The conversation ID you want to route
*   The queue ID you want to assign the conversation to

### **Create a work item to assign a conversation to a queue**

To create a work item that assigns a conversation to a specific queue, send a POST request to the work items endpoint.

****Endpoint:**** `POST https://{orgname}.api.kustomerapp.com/v1/routing/work-items`

****Request body:****

****`   `****

****`   `****

****`   `****

****`   `****

****`   `****

****`   `****

****`   `****

****`   `****

****`   `****

****`{`****

    ****`"resource": {`****

        ****`"id": "{conversationId}",`****

        ****`"type": "conversation"`****

    ****`},`****

    ****`"queue": {`****

        ****`"id": "{queueId}"`****

    ****`}`****

****`}`****

  

****Note:**** The queue field accepts only a flat object with the queue id. Do not nest it under a relationships or data wrapper.

### **Verify the work item was created**

To confirm the conversation was assigned to the queue, send a GET request:

****Endpoint:**** `GET https://{orgname}.api.kustomerapp.com/v1/routing/conversations/{conversationId}/work-items`

In the response, confirm:

*   `attributes.status` is `"queued"` or `"assigned"`
*   A queu  relationship exists in the relationships object

If the queu relationship is missing from the response, the work item was not correctly assigned to the queue.

### **Troubleshoot common errors**

**Error**

**Cause**

**Fix**

`400 badparam: Additional properties not allowed`

Request body includes unsupported fields like `relationships` or `data` wrappers

Use the flat request body format shown above

Work item created but no queue in response

Queue ID may be invalid or the conversation is already assigned

Verify the queue ID exists and the conversation does not already have an active work item

* * *

### 19\. **Investigate customer profile merges**

Customer merge events may not always appear in the standard Audit Log UI. To view the full merge history for a customer profile, use the Kustomer API.

Send a GET request to `/v1/customers/{customerId}/merges` to retrieve a list of all merge events for that customer, including:

*   The date and time of the merge.
*   Whether the merge was manual or automated.
*   The source and target profile IDs.
*   The number of conversations on each profile before and after the merge.
*   The user who performed the merge.

> ****Note:**** A single merge operation may generate two merge event records. This is expected behavior and does not indicate a duplicate merge.

* * *

### 20\. **Report on tag usage per agent using the Audit Log API**

The Kustomer reporting UI does not support a combined report showing tag usage broken down by agent and date. To build this report, query the Audit Log API and aggregate the results externally.

Send a GET request to `/v1/audit-logs` with filters for the "tag" action type and a date range. Each audit log entry includes:

*   `performedBy` — The agent who applied the tag.
*   `tag` — The tag that was added or removed.
*   `createdAt` — The timestamp of the action.

Export these records to a spreadsheet or data warehouse and create a pivot table grouped by agent, tag, and date.

* * *

### 21\. **Message body character limits by channel**

When you create a message through the Kustomer API, the following character limits apply to the message body based on the channel:

**Channel**

**Maximum characters**

Email

10,240

Chat

10,240

SMS

1,600

Facebook DM

2,000

If your integration sends messages that may exceed these limits, cap the message body at 5,000 characters and split longer content into multiple messages.

> ****Note:**** These limits apply to the Kustomer API message body field. Third-party channel providers (for example, Twilio for SMS) may enforce additional limits.

* * *

### 22\. Create a Threshold-based alert workflow with the Search API

You can build a workflow that monitors conversation volume and sends an alert (via email or Slack) when a threshold is exceeded. This is useful for detecting high-volume periods or monitoring specific channels like SMS.

#### **Build the alert workflow**

1.  Create a scheduled workflow that runs at a regular interval (for example, every hour).
2.  Add a ****REST API**** action step that calls the Kustomer Search API endpoint (`/v1/customers/search`) with your search criteria (for example, inbound SMS conversations created in the last hour).
3.  Add a ****Condition**** step that checks if the `meta.total` value in the response exceeds your desired threshold (for example, 75 or 100).
4.  If the condition is met, add a ****Send Email**** or ****Slack Notification**** action step to alert the appropriate team.

****Tip:**** Use the debug log to test the workflow with open search criteria first, then narrow the filters once you confirm the Search API response structure.

* * *

### 23\. Retrieve knowledgebase articles via the API

You can use the Kustomer API to retrieve knowledge base article content programmatically. This is useful for hosting FAQ content on your own domain with custom formatting or SEO schema markup.

#### **API endpoints**

*   ****List all articles:****`GET /v1/articles`
*   ****Get a single article:****`GET /v1/articles/{id}`

Full API reference: [Kustomer API documentation](https://developer.kustomer.com/kustomer-api-docs/reference/getarticles)

#### **Authentication**

Include your API key in the Authorization header:

`Authorization: Bearer YOUR_API_KEY`

Create an API key under ****Settings**** > ****Security**** > ****API Keys****. The key must have read permissions for knowledge base resources.

#### **Response format**

The API returns article content in HTML format. Parse the `attributes.body` field to extract the article HTML for rendering on your site.

* * *

### 24\. Conversation search API endpoint

To search for conversations programmatically, use the `/v1/customers/search` endpoint with the `queryContext` parameter set to `conversation`

****Important:**** The `/v1/conversations/search` endpoint is not a supported Kustomer API endpoint. Use `/v1/customers/search` with `queryContext: "conversation"` instead.

#### **Example request**

```
POST /v1/customers/search
```

Include the `queryContext` parameter in the request body along with your search criteria:

`   `

`   `

`{`

  `"queryContext": "conversation",`

  `"and": [`

    `{"conversation_status": {"equals": "open"}},`

    `{"conversation_name": {"contains": "your search term"}}`

  `]`

`}`

  

See the [API introduction](https://help.kustomer.com/api-introduction-BkwVN42zM) for authentication and request format details.

* * *

### 25\. Deleting a Company via the API

You cannot delete a company from the Kustomer UI. Companies are deleted through the API, which performs a soft delete — the company is removed from search and the UI but retained in the database.

*   ****Delete one company:**** send a request to the [Update company attributes](https://developer.kustomer.com/kustomer-api-docs/reference/updatecompanyattributes) endpoint with `deleted` set to `true`.
*   ****Delete companies in bulk:**** use the [Bulk batch update companies](https://developer.kustomer.com/kustomer-api-docs/reference/bulkbatchupdatecompanies) endpoint.

The API key you use must have a role that grants write access to companies.

* * *

### 26\. Send an SMS or email reply from a workflow using the REST API

Use the drafts endpoint, not the messages endpoint, to actually deliver a message.

1.  In your REST API: JSON action step, set __Method__ to `POST` and __URI__ to `https://[orgname].api.kustomerapp.com/v1/customers/{{steps.1.customer.id}}/drafts`.
2.  In the __Data__ field, include `channel`, `app`, `conversation`, `from`, `to`, `body`, and `sendAt`. Set `app` to the exact name shown in ****Settings > Apps**** — case- and space-sensitive.
3.  Create a dedicated API key with the roles `org.permission.draft.create`, `org.user.draft.read`, and `org.user.draft.write`.

****Note:**** `POST /v1/conversations/{conversationId}/messages` creates a UI-only record — it never delivers to the customer.

4.  If nothing sends with no error, open ****View Errors**** and use ****Test Workflow**** with real IDs to confirm the payload and app name match exactly.

* * *
