# Introduction

Welcome to Saleschat documentation

Saleschat is designed to streamline sales communications by leveraging WhatsApp as a secure and compliant channel, especially for enterprise-level sales teams.

This documentation will guide you through everything from getting started with account setup to integrating with your CRM, managing multiple Contacts / Leads with the same phone number, and ensuring compliance with industry regulations.

### Getting started with Saleschat

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td></td><td></td><td><strong>Onboarding</strong></td><td><a href="/pages/8ovfl4YOfcHjAkZGXJpt">/pages/8ovfl4YOfcHjAkZGXJpt</a></td></tr><tr><td></td><td></td><td></td><td><strong>Whatsapp (WABA) templates</strong></td><td><a href="/pages/b5pIIBiN1qkgbYVmifT3">/pages/b5pIIBiN1qkgbYVmifT3</a></td></tr><tr><td></td><td></td><td></td><td><strong>Basic CRM Integration Tutorial</strong></td><td><a href="/pages/5YCXndkM3PjcaMVG30Gq">/pages/5YCXndkM3PjcaMVG30Gq</a></td></tr><tr><td></td><td></td><td></td><td><strong>Webhooks</strong></td><td><a href="/pages/gOIK6quIPrZHUtlLtV9u">/pages/gOIK6quIPrZHUtlLtV9u</a></td></tr></tbody></table>


# Onboarding

This guide outlines the steps for onboarding new customers, including user and organization setup, API key generation, and WABA registration.

## User & Org Creation

{% hint style="info" %}
We have disabled public signups.
{% endhint %}

Saleschat's team will create the organisation and add a user from your organisation with Owner role.

> Role can be edited later and another user can be granted owner role.

Next steps require the following:

1. Organisation
   1. org\_id
2. [User](/api-documentation/user)
   1. user\_id
   2. email\_id
   3. password

## Partner API Key

User can generate a partner API key from the dashboard.

1. Click on User Account
2. Click on Organization Info
3. Click on Company API Keys
4. Click on New API Key and follow the flow.
5. Copy the newly generated API key

## WABA Onboarding

### Register directly with Meta

Complete the embedded signup flow [here](https://app.saleschat.pro/meta).

{% hint style="info" %}
Note that a credit card is required to be registered as a payment method.
{% endhint %}

### Interakt Embedded Signup Flow

Complete the embedded signup flow [here](https://app.saleschat.pro/meta).

### Gupshup Enterprise Account

1. Work with Gupshup to create a username and password for the WABA account that you want Saleschat to use.
2. Provide us the username and password.

Once WABA is registered with Saleschat, we will provide you the following details which you can use when you would like to integrate our APIs:

1. remote\_waba\_id
2. remote\_phone\_id


# Whatsapp (WABA) Templates

Whatsapp (WABA) Template support on Saleschat, with the functionalities and shortcomings based on the WABA provider

### Overview

Saleschat lets you fetch and manage *templates* registered via your preferred BSP (Business Service Providers) or directly on Meta.

> **Can I register templates that are still&#x20;*****Pending Review*****?**\
> No. Templates must be in `APPROVED` state unless you explicitly call the admin-only bypass flow used by the auto-sync mechanism.

> **What does enable / disable mean for a template?**
>
> *Enabled:* When a template is enabled, it can be accessed and used by automations and APIs. This means it is available for workflows and integrations.
>
> *Disabled:* Disabled templates cannot be utilized by automations or APIs. They are essentially inactive, so they won't appear & cannot be used, in automated processes until re-enabled.

> **What does visible mean for a template?**
>
> **Visibility** determines whether an agent can see and select the template.
>
> * If a template is **visible**, agents will be able to find and use it on their chats screen
> * If a template is **hidden**, it will not be displayed to agents

> **What are quick replies on the template page?**
>
> **Quick replies** are conversational templates designed to keep conversations flowing smoothly. These are *not* Meta (Facebook) templates—they are custom responses, which you can register on Saleschat.
>
> Quick replies allow agents to maintain conversation quality by providing prompt, contextually appropriate responses while a chat session is active.

### Supported Template Components

| Component          | Mandatory                      | Parameter support | Notes                                                                                                                        |
| ------------------ | ------------------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Body**           | ✅ Yes                          |                   | We support only Numbered placeholders `{{1}}...`Placeholders are not supported.                                              |
| **Header (Media)** | ✅ Yes                          |                   | Only `IMAGE`, `VIDEO`, or `DOCUMENT` formats are allowed. Text / Location headers are not supported.                         |
| **Footer**         | ✅ Yes (*Meta & Interakt only*) |                   | *Gupshup* templates **cannot** contain a footer at all.                                                                      |
| **Buttons**        | ✅ Yes                          |                   | Supported button types: `URL`, `PHONE_NUMBER`, `QUICK_REPLY`. URL Buttons can have only one parameter at the end of the URL. |
| **Carousel**       | ❌ Not supported                |                   |                                                                                                                              |

> **What if I want to use different URLs for the same template instead of registering multiple templates?**
>
> Saleschat allows you to use the below provided URL as a method for providing dynamic buttons to have different urls. Use the following URL while you register the template, & pass any URL you want as the parameter to redirect.
>
> ```java
> https://apis.saleschat.pro/cta?redirect=
> ```

> **What if I want to measure clicks on URLs?**
>
> You can use UTM query parameters in the URL. Further if you like UTM parameter to be configurable, then use URL Buttons with a parameter. Google analytics or similar tools can give you analytics based on UTM parameters (link to google analytics documentation).

> Is there any alternative to UTM parameters / Google analytics?
>
> Lastly if you use URL redirect as explained above, then Saleschat can run the analytics for you
>
> example of how Saleschat URL redirect works?

### Parameter Types

Saleschat can be auto\_fill parameter values if they are available. This is an added functionality on top of Meta Templates. This has two major benefits

1. Enterprises can run Automations using templates with parameters.
2. Agent's do not have to repeatedly type the parameter values while sending templates.

| Type           | Purpose                                                             | Tag rules / Tag values                                                                                            |
| -------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **AUTO\_FILL** | Saleschat fills the value automatically if provided via integration | <p>Supported tags : <code>sc.contact.name</code><br><code>sc.user.name</code></p>                                 |
| **USER\_FILL** | Value supplied by your agent before sending                         | <p>Tag <strong>must NOT</strong> start with <code>sc.</code><br>Tag <strong>must be < 128 characters</strong></p> |

> **Can different parameters have the same tags ?**
>
> No, tag values must be unique across the whole template. This ensures there are no duplicated tag identifiers within a single template.

> **Can agents change the media when sending a template with AUTO\_FILL headers?**
>
> No, agents cannot change the media file when sending a template that uses AUTO\_FILL headers. The media file must be specified during template registration and remains fixed.

{% hint style="info" %}
Editing Parameter types and tags, once registered, is currently not supported, although it is in our development pipeline. If you would like us to expedite the same, then please reach out to us.
{% endhint %}

### Template Webhooks

The following webhooks are available for respective BSPs and are also handled by Saleschat.

| Webhook type                  | Meta | Gupshup Enterprise | Interakt |
| ----------------------------- | ---- | ------------------ | -------- |
| **Template Status Update**    | ✅    | ✅                  | ✅        |
| **Template Quality Score**    | ✅    | ✅                  | ✅        |
| **Template Category Change**  | ✅    | ✅                  | ✅        |
| **Template Component Change** | ✅    | ❌                  | ❌        |

> **How can I configure Gupshup Enterprise to send Webhooks to Saleschat?**
>
> You can configure Template webhooks to be sent to the following callback URL
>
> ```java
> "https://apis.saleschat.pro/v1/gupshup/comms/waba/callback/template"
> ```

> **How do we update template component changes on Saleschat if my provider is Gupshup Enterprise and Interakt?**
>
> If you've updated the template on gupshup/interakt, you would need to sync those changes manually on saleschat, see section below

### Updating Templates Manually

Click on the Sync icon on the Template dashboard page for the template you want to sync. It will fetch the changes from Meta and apply it on Saleschat. If the number of parameters have changed between the previous template, and the new template, then you would require to manually re-register the new template by clicking the arrow next to the template name, after it's synced.

<figure><img src="/files/CcP2um3DaDf8279fZGSU" alt=""><figcaption></figcaption></figure>

> **What if I do not update the template on Saleschat?**
>
> If you do not update the template that's undergone a change on Meta, the template deliveries will fail.

> **What if the template is deleted on Meta?**
>
> Please disable the template on saleschat if template is deleted on Meta. Since we dont allow deleting a template on Saleschat as of now

***

*Last updated: 23rd July 2025*


# Basic CRM Integration Tutorial

This tutorial will guide you through the essential steps for a basic integrating between your CRM and Saleschat.

{% hint style="info" %}
Without this integration, Saleschat can still be used via its dashboard, but key features like **number leakage protection** and **programmatic agent assignment** will not be available.
{% endhint %}

## Step-by-step guide

We recommend that you provide the following two buttons on your CRM:

1. Login
2. Chat

> **Where should I provide these buttons?**
>
> The Login button can be provided as an action within accounts or integration section
>
> The Chat button should be provided for each lead, within quick actions for the lead (for ex. next to the dialer).

The functionalities for each of these buttons is explained as below.

### 1. Login

Users can use the “Login” button to login to Saleschat which should open a new Saleschat tab.

When the login button is clicked, the following steps should be performed at the client:

1. [Generate a magic link](/api-documentation/user#v1-org-orgid-user-userid-magiclink) for the user.
2. Open the generated magic link in a new tab.

{% hint style="info" %}
Users can be created in Saleschat in advance using the [**Create User API.**](https://apis.saleschat.pro/public/swagger-ui/index.html#/user-controller/createUserAndAddToOrg)

This can be a batch operation via a script and need not be a part of logic within your CRM.

Do make sure that the userId's of users that are created via the API are recorded in your system.
{% endhint %}

{% hint style="warning" %}
Saleschat's dashboard allows ONLY one tab to be active at any given time. If a new tab is opened up all the previous tabs become inactive.
{% endhint %}

### 2. Chat

Users can use the "Chat" button to get access to the Chatroom with the customer. The access to the Chatroom will be granted basis the business logic.

> **Where will the User see the Chatroom?**
>
> If the business logic permits and the API operations are successful, the user will automatically see the Chatroom at the top of the list of Chatroom within Saleschat's chat dashboard. The User should not "Login" to Saleschat for each customer.

We recommend the following business logic:

<table><thead><tr><th width="578">Business logic</th><th>API documentation</th></tr></thead><tbody><tr><td>Create a Lead in Saleschat if not created already.</td><td><a href="/pages/gewOBDR1vnWf1YnTafrd#post-v4-orgs-orgid-leads">Link</a></td></tr><tr><td>Assign a lead to a user</td><td><a href="/pages/gewOBDR1vnWf1YnTafrd#put-v4-orgs-orgid-leads-leadid-assign">Link</a></td></tr></tbody></table>

> #### **What if I want to re-assign a lead to a different user?**
>
> To reassign a lead to a different user, call the **Assign API** again with the new user details. The system will automatically update the assignment.

> #### **How will I create a chatroom for a lead?**
>
> A chatroom is automatically created when you call the **Assign API**, if one does not already exist for the lead. No manual creation is required.

> #### **What if I prefer having manager and agent in the same chatroom with the customer?**
>
> While practices on personal Whatsapp app follow these conventions, it is not scalable for the manager and it leads to a state where it is practically impossible for the manager to keep track of all the conversations.
>
> We recommend having only the agent in the chatroom along with the customer. Each manager has access to agent metrics and chats between the agents and the customers.

> #### **How will the customer know which agent are they speaking with?**
>
> We annotate the name of the agent with each chat so as to maintain a personal touch between the agent and the customer.

> #### **How will the agent know which customer the agent is speaking with**
>
> The chatroom name is a combination of CRM\_ID, First Name and Last Name of the Lead that is created.

{% hint style="info" %}

#### **Explicit Success & Error Notifications:**

Each of the API to create and assign a Lead responds with appropriate error code and error message in case of a failure and we suggest that you display them explicitly when the user is interacting with the Chat button on your CRM.
{% endhint %}

### Basic Database Schema

| Field             | Description                         |
| ----------------- | ----------------------------------- |
| **User table**    |                                     |
| `id` (PK)         | Primary Key of the User table       |
| `crm_user_id`     | CRM-specific user ID                |
| `sc_user_id`      | Saleschat user ID                   |
| `sc_magic_link`   | Magic link for user login           |
| `sc_expiry_ts`    | Expiry timestamp for the magic link |
|                   |                                     |
| **Lead table**    |                                     |
| `id` (PK)         | Primary Key of the Lead table       |
| `crm_customer_id` | CRM-specific customer ID            |
| `sc_lead_id`      | Saleschat Lead ID                   |
|                   |                                     |


# Whitelist URLs

URLs to be whitelisted for Saleschat app

You will have to whitelist the following URLs within the network which hosts your CRM as well as the network that the agents are logged in to while using the CRM and Saleschat.

**Note:** We have listed the root domains below, although you will have to enable its subdomains including multi level subdomains

> **Important:** None of these are social media domains. For example, `facebook.net` is not `facebook.com` — visiting facebook.net in a browser will show "We can't connect to the server at facebook.net." Similarly, `googleapis.com` will show "The requested URL / was not found on this server." These are infrastructure/service domains used by Meta, Google Cloud, Firebase, and Analytics — they do not grant access to any social media websites.

<table><thead><tr><th width="202.57421875">Domain</th><th width="562.5">Purpose</th></tr></thead><tbody><tr><td>saleschat.pro</td><td>Saleschat's domain</td></tr><tr><td>cloudconverse.in</td><td>Saleschat's parent company's domain, used to host our chat servers</td></tr><tr><td>posthog.com</td><td>Experimentation tool used by Saleschat</td></tr><tr><td>facebook.net</td><td>Required by Meta (infrastructure domain, not facebook.com)</td></tr><tr><td>googleapis.com</td><td>Required for Firebase as well as other Google Cloud / Analytics services</td></tr><tr><td>googletagmanager.com</td><td>Required for Google Analytics</td></tr><tr><td>google-analytics.com</td><td>Required for Google Analytics</td></tr><tr><td>mtalk.google.com</td><td>Required for browser push notifications via FCM (Firebase)</td></tr></tbody></table>


# Webhooks

This page lists all the web hooks that we push to the web hook URL configured for your organisation

## Contact Assigned

Version 1.0

```json
{
	"type": CONTACT_ASSIGNED,
	"version":<double>,
	"payload": {
		"contact_id": <string>,
		"user_id": <string>,
		"is_handover": <boolean>,
		"is_assigned" : <boolean>
	}
}
```

## Chatroom Creation

Version 1.0 & 1.1

```json
{
	"type": CHATROOM_CREATED,
	"version":<double>,
	"payload": {
		"chatroom_id": <string>,
		"external_ref_id": <string>,
		"chatroom_type": <enum CONTACT | AFFILIATE >,
		"is_inbound" : <boolean>
	}
}
```

## Chatroom Status Update (Active/Deactive/Expired)

Version 1.0 & 1.1

```json
{
	"type": CHATROOM_ACTIVATED | CHATROOM_DEACTIVATED | CHATROOM_EXPIRED,
	"version":<double>,
	"payload": {
		"chatroom_id": <string>,
		"chatroom_type": <enum CONTACT | AFFILIATE >,
		"status_update_ts": timestamp
	}  
}
```

## Contact Expired

Version 1.0 & 1.1

```json
{
	"type": CONTACT_EXPIRED,
	"version":<double>,
	"payload": {
		"contact_id": <string>
	}  
}
```

## Send Template Message

Version 1.0 & 1.1

```json
{
	"type": SEND_TEMPLATE_MESSAGE_STATUS,
	"version":<double>,
	"payload": {
		"request_id": <string>,
		"chatroom_id": <string>,
		"remote_phone_id": <string>,
		"remote_waba_id": <string>,
		"remote_template_id": <string>,
		"status": <enum PERMANENTLY_FAILED | DELIVERED>,
		"err_code": <String>,
		"err_reason": <String>
	}  
}
```

## Media Received

Version 1.0 & 1.1

> This webhook will be retried for a maximum of 3 days before being marked as failed.

```json
{
	"type": MEDIA_FILE,
	"version":<double>,
	"payload": {
		"phone_number": <e164_format string>,
		"file_name": <string>,
		"mime_type": <string>,
		"remote_phone_id": <string>,
		"remote_waba_id": <string>,
		"chatroom_id": <string>,
		"org_id": <string>,
		"media_id": <String>
	}  
}
```

## Media Received with Classification

Version 1.0 & 1.1

```json
{
	"type": MEDIA_FILE_WITH_CLASSIFICATION,
	"version":<double>,
	"payload": {
		"phone_number": <e164_format string>,
		"file_name": <string>,
		"mime_type": <string>,
		"remote_phone_id": <string>,
		"remote_waba_id": <string>,
		"chatroom_id": <string>,
		"org_id": <string>,
		"media_id": <String>,
		"classification": {
			"suggested_labels": list<string>,
			"suggested_labels_status": <enum ACCEPTED | REJECTED>,
			"user_input_labels": list<string>
		}
	}  
}
```

## Contact Opt Out Webhook

Version 1.0 & 1.1

```json
{
    "type": CONTACT_OPT_OUT,
    "version":<double>,
    "payload": {
        "phone_number": <e164_format string>,
        "chatroom_id": <string>,
        "opt_out_ts": <timestamp>,
        "opt_out_source": {
            "type": <enum TEMPLATE_BUTTON>,
            "template_id" : <string>,
            "button_id": <string>
        }
    }
}
```

## Analytics Dump

Version 1.0 & 1.1

Note that the file format may vary based on webhook version.

For more details refer to [Metric Dumps](/application/metric-dumps)

```json
{
    "type": ANALYTICS_DUMP_FILE,
    "version" : <double>
    "payload": {
        "metric_type": <string>,
        "granualarity": <enum DAILY | WEEKLY>,
        "start_time": <timestamp>,
        "file_id": <string>
    }
}
```

For downloading the file use the [download signed URL API](/api-documentation/media) with the above obtained *file\_id*

Analytics Metric Type:

* MESSAGE\_DUMP
* AGENT\_ANALYTICS


# Contacts, Chatrooms & Customer Lifecycles

This page describes Contact, Chatroom and their lifecycle as well as how to handle multiple Contacts with the same Phone Number

## Single Chatroom Per Contact (Whatsapp's Restrictions)

Whatsapp allows only one Chatroom between two Phone Numbers. If you have an existing Chatroom with a Customer on Whatsapp, you can either chat with the Customer in that Chatroom or you can delete the Chatroom and start a fresh conversation. There are no scenarios where you can have two simultaneous Chatrooms with the Customer in 1-1 Chats.

Having said that, since we use one Whatsapp Business Account for a team as large as your Organisation's we understand that you may end up having multiple Contacts / Leads in your CRM with the same Phone Number.

We handle such scenarios via Customer Lifecycle as written below.

## Multiple Contacts with the same Phone Number

Saleschat lets you create multiple Contacts with the same Phone Number as long as

1. The Contacts have a distinct crm\_id
2. The Phone Number is not used for an Affiliate Chatroom

{% hint style="info" %}
Affiliate Chatrooms are like any other Chatrooms although mainly used for speaking with back office, partners etc. where multiple users are speaking with the affiliate simultaneously within the same Chatroom. Contact Saleschat's Team for more information on affiliate Chatrooms.
{% endhint %}

<figure><img src="/files/Mw8Pk18QRjV5xfC5qAK1" alt="" width="349"><figcaption><p>Create contact flowchart</p></figcaption></figure>

## Chatroom per Contact

Saleschat lets you create one Chatroom per Contact as long as there is no other active Chatroom for the Contact's Phone Number using the same WABA Phone.

<figure><img src="/files/kit3DPrNWxgGtn8ZjpUJ" alt="" width="375"><figcaption><p>Create chatroom flowchart</p></figcaption></figure>

## Activate / Deactivate a Chatroom

A Chatroom can be activated/deactivated. Activated/Deactivated can be considered as enabled/ disabled.

A deactivated chatroom can be re-activated as long as there is no other active chatroom for a different Contact with the same Phone Number using the same WABA Phone.

{% hint style="info" %}
At any given time only one Chatroom for a Phone Number within a WABA Phone can be active. If two Contacts have the same Phone Number, then a Chatroom for only one of those Contacts can be in active state.
{% endhint %}

> **How do I deactivate a Chatroom?**
>
> Organisations can configure 'n' number of days since the last message from the Contact in a Chatroom after which the Chatroom will be deactivated.
>
> Alternatively Organisations can deactivate the Chatroom using [Deactivate Chatroom API](/deprecated-apis/chatroom-deprecated#v1-org-orgid-contacts-chatroom-chatroomid-deactivate).

> **How do I activate a Chatroom?**
>
> Organisations can activate the Chatroom using [Activate Chatroom API.](/deprecated-apis/chatroom-deprecated#v1-org-orgid-contacts-chatroom-chatroomid-activate)

> **How do I communicate with a deactivated Chatroom?**
>
> Saleschat disallows any further messaging to a deactivated Chatroom. You first need to activate the Chatroom.

{% hint style="info" %}
Only messages **sent via Campaigns** **are allowed** in a deactivated Chatroom. Contact Saleschat Team to learn more about Campaigns.
{% endhint %}

> **What if I receive a message from a Phone Number for whom the Chatroom is deactivated?**
>
> If there is another active Chatroom for this phone number, then Saleschat will route the incoming message to that active Chatroom
>
> If there is no other active Chatroom for this phone number, then Saleschat will route the incoming message to the latest deactivated Chatroom and also activate that Chatroom.

## Expire a Contact & Chatroom

A Contact can be expired. Expired can be considered similar to soft delete, where the data of the contact as well as that of the Chatroom and the chats for this contact are not deleted. An expired Contact / Chatroom cannot be reverted.

> **How do I expire a Contact?**
>
> As of now, we allow organizations to set a configuration to expire the contact within 'n' number of days of creation.

> **How do I communicate with an expired Contact?**
>
> Saleschat disallows any further messaging to an expired Contact. You may create a new Contact with the same phone number and a different crm\_id and a new Chatroom for this new Contact to be able to communicate.

{% hint style="info" %}
Even messages sent via a Campaign are disallowed in an Expired Chatroom
{% endhint %}

> **What if an expired Contact messages us?**
>
> If there is no other non-expired Chatroom for this phone number, then Saleschat will route the incoming message to the latest expired Chatroom.
>
> Saleschat further allows you to configure an auto-trigger response for every message received in an expired Chatroom

<figure><img src="/files/FzUHPG3QMePaibU6GTgk" alt="" width="314"><figcaption><p>Expire contact chatroom</p></figcaption></figure>


# Multiple WABA & Phone Numbers

Multiple WABA accounts and Multiple Phone Numbers in each WABA account.

## Overview

Saleschat allows organizations to integrate multiple **WhatsApp Business Accounts (WABAs)** under a single organization. This feature is ideal for companies with multiple verticals, products or brands (**divisions**). Each WABA can have its own message templates.

Saleschat also allow **Multiple Phone Numbers for a single WABA.** This feature is ideal for companies who need to hand over multiple leads for the same contact to various locations and/or sales agents (**branches**). Each Phone Number will share the templates defined for that particular WABA.

***

## Use Cases

* **Divisions (Multiple WABA)**
  * A lending organization operating across different loan products like Personal Loans, Business Loans & Home Loans can setup separate WABAs for each loan product, ensuring customer queries are answered by the appropriate team with the relevant division.
* **Branches (Multiple Phone Numbers for a Single WABA)**
  * A lending organization that has a single loan product, for ex. student loan where multiple leads have to be created one for each child student although the contact for each lead is the same parent.
  * An organization with retail presence which needs to create multiple leads for a single inquiry such that each lead is routed to a distinct branch.

Contact Saleschat for any further information or clarification.

> **How does Activate / Deactivate Chatroom differ from Multiple WABA and Multi Phone**
>
> Activate/Deactivate Chatroom is useful for an organization
>
> * in most scenarios will have a single lead for a phone number and multiple leads for the same phone number is an anomaly.
> * They do not want different agents to speak to the same agents simultaneously and maintain only one active lead at a time.
> * Or just that they do not want to invest in more than one phone number at the moment.
>
> Alternatively if the organization would have multiple leads for the same phone number more often than not then they should use Multi WABA or Multi Phone or a combination of both as per their use case.
>
> Chatroom lifecycle is enforced per WABA Phone Number.

> **How will Users see chatrooms across WABA?**
>
> Users will see all the chatrooms in a single Dashboard.

> **How do I create a chatroom for a specific WABA and Phone Number?**
>
> You can specify the WABA and Phone Number Ids that you want to use to create chatroom. Currently we allow only one chatroom per contact irrespective of any number of WABAs registered with us.
>
> If you have any requirements, please reach out to us.


# Sending messages via automation

This section deals with automation in chats to send messages and run workflows.

### Basic chat flow

A basic chat flow where agent is a participant of the chatroom along with capabilities to send one-way messages via API (for ex. at the start of the chatroom or updates in between) is achieved as follows.

1. Create a contact
2. Create a chatroom with participants
3. Send a message

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf-3OyKxVTcIMjKz7tBIjIDJYVQ5IT-natRYgy_WIT3rZQIgk5Dxo9EKv0NVjOFBqryKBb-ewSzbyqJU-a5AA60qp-4ytQqNArDclVVRCrvuVL0XaF9VJ8B08xcRrS-xVGZW8OOgw?key=bGSRkjs4wA34jhlbBI21EoKd" alt=""><figcaption><p>Basic chat flow</p></figcaption></figure>

{% hint style="info" %}
Saleschat provides APIs for basic chat flow.
{% endhint %}

### Send Template Message API

Since WABA requires initialization of a new chat session via a pre-approved template, the API currently allows sending of only template messages via API.

Even during the conversation, any interactive message, for example, messages with buttons, also need to be sent as a template.

### Workflows using templates

Organizations that want to optimize agents time may want to send messages and also process the response via workflow automation.

To be able to achieve this, the Send Template Message API provides a `relay_response` query parameter.

{% hint style="info" %}
**Where will I receive response from the customer?**

The response will be sent to the webhook that is configured for the organization. If the webhook is not configured then the response will not be sent.
{% endhint %}

{% hint style="info" %}
**Which responses will be relayed back to the webhook?**

Only interactions with the templates that have buttons will be relayed back to the webhook. Any message other than interaction with the template, for example, a free flow response will not be sent back to the webhook
{% endhint %}

{% hint style="info" %}
**Will agent be allowed to chat during the workflow?**

Yes, agent will be allowed to send messages even while the workflow is sending messages. The interactions with the template for which relay\_response is set will still be relayed back to the webhook.
{% endhint %}

<figure><img src="/files/DKMjtQw2feQHiletTgIP" alt=""><figcaption></figcaption></figure>

### Silent messaging / Bump

In a basic chat scenario, each message bumps the chatroom to the top of the chatroom list.

Organizations may require that while the workflow automation is sending messages as well as any interaction on the template message remain silent and do not bump the chatroom to the top.

To be able to achieve this, the Send Template Message API provides 2 parameters -

1. `bump` - when set to `false` , the chatroom will not be bumped to the top of chatroom list when a template message is sent.
2. `bump_response` - when set to `false` , any interaction with the template message will not bump the chatroom to the top of the chatroom list.

{% hint style="info" %}
Free flow (non-interactive) response from the customer will always bump the chatroom to the top of the chatroom list.
{% endhint %}

<figure><img src="/files/z8BLexuQVSdDnsUCkzKj" alt=""><figcaption></figcaption></figure>

### Optimizing Agent Participation

A new chatroom for a participant, unlike a message, will always bump it to the top of the chatroom list.

In some cases, bots can handle the initial conversation with a new customer. The system sends a message and waits for the customer to respond. On the basis of handover rules, a human agent can step in to manage the interaction. This ensures efficiency and allows agents to focus on engaged customers.

To be able to achieve this, the Create Chatroom API provides a flag `assign_on_handover`

This would also make sure that the chatroom is created but not bumped in the list of chatrooms for the agent, because the agent is not yet a participant of the chatroom.

{% hint style="info" %}
What do you mean by handover?

1. If `assign_on_handover` is set to `true` , then the agent will be assigned to the chatroom only when -
   1. Customer sends a free flow message
   2. There is an interaction with a template sent via STM API and `relay_response` flag is set to `false` (default is `false` )
2. Explicit reassignment using Chatroom Reassign API
   {% endhint %}

{% hint style="info" %}
Agent participation can only be optimized at the time of chatroom creation.
{% endhint %}

### Explicit Reassignment

In some cases, organizations may want to send a message to a customer and not wait for response even though `assign_on_handover` was set to `true` .

Consider the following scenario -

1. A chatroom was created with `assign_on_handover` set to `true`
2. A message was sent via STM
3. Customer neither interacted with the STM message nor responded with any free flow message
4. Organization would like the agent to follow up manually

To achieve this, you can re-assign chatroom.

On explicitly reassigning in this manner, the pending `assign_on_handover` will be discarded.


# Events & Attributes

#### Overview

SalesChat tracks two types of data for your leads and users:

* **Attributes** — Attributes are custom fields you can attach to your **users** and **leads** (e.g., process, product code, policy number)
* **Events** — things that happen, carrying event-scoped attributes (e.g., stage change, disposition update, call details)

Automations are triggered based on events and attributes are used by attribute matcher to filter such events.

#### Permanent Attributes

Permanent attributes are properties that rarely change and are scoped for the life of the lead.

Permanent attributes are key-value pairs stored on a lead or user. They accumulate over time — each update merges new values with existing ones.

**How they work:**

```
API call 1:  { "process": "Issuance" }     → Lead has: { process: Issuance }
API call 2:  { "product_code": "P1" }      → Lead has: { process: RM, product_code: P1 }
API call 3:  { "process": "Sales" }        → Lead has: { process: Sales, product_code: P1 }
```

* New keys are added
* Existing keys are updated (latest value wins)
* Keys not included in the update are preserved

**Use cases:** CRM sync fields, customer segments, agent assignments, any data that defines "who" the lead or user is.

#### Events

Events represent things that happen to a lead. Each event has a **type** and carries **event attributes** that are scoped to that specific event.

**Key difference from permanent attributes:** Event attributes are properties that change very often and are scoped for the life of the event. The next event has its own attributes.

**API — Disposition update (triggers an event):**

`PUT /v2/orgs/{orgId}/contact/{contactId}/disposition`

```json
{
    "stage": "INTERESTED",
    "disposition": "WARM",
    "call_time": "10:30",
    "payment_amount": "5000"
}
```

All fields beyond `stage` and `disposition` are accepted as additional event attributes.

#### How Attributes and Events Work Together

Event triggers automation, attribute matcher matches / filters based on the attributes.

```
Permanent attributes (from lead profile)
    +
Event attributes (from the triggering event)
    =
Merged attributes → evaluated against matcher conditions
```

**If a key exists in both, the event attribute takes precedence.**

**Example:**

Lead has permanent attributes: `{ process: "RM", product_code: "P1" }`

A disposition event arrives with: `{ stage: "INTERESTED", disposition: "WARM" }`

The matcher evaluates against the merged set:

```
process = RM              (from permanent)
product_code = P1         (from permanent)
stage = INTERESTED        (from event)
disposition = WARM        (from event)
```

You can configure matcher conditions against any of these — e.g., trigger automation when `stage = INTERESTED` AND `process = RM`.


# Attribute Matcher

#### What are Attributes?

Attributes are custom fields you can attach to your **users** and **leads**. They extend the standard profile information SalesChat already tracks — letting you store details like sales process, campaign source, product code, or location.

Attributes are typically set via integrations and APIs (e.g., synced from your CRM). Once set, they become available throughout SalesChat — including in the Attribute Matcher, where you can build rules based on them.

For details on how attributes relate to events, see Events & Attributes.

***

#### What is an Attribute Matcher?

An Attribute Matcher is a rule engine that lets you control platform behaviour based on user and lead attributes. You define conditions, and SalesChat evaluates them in real time.

**Where it's used:**

| Feature                 | How Matcher is Used                                               |
| ----------------------- | ----------------------------------------------------------------- |
| **Contact Free Flow**   | Controls which users can send freeflow (non-templated) messages   |
| **Automation Triggers** | Determines whether an automation should fire when an event occurs |

***

#### Using Attribute Matcher in Automation

When you create an automation with the `UPDATE_CONTACT_STAGE_DISPOSITION` event type, you configure trigger conditions using the Attribute Matcher.

**How it works:**

1. An event occurs (e.g., a lead's disposition is updated)
2. SalesChat merges the lead's **permanent attributes** with the **event attributes**
3. The matcher evaluates your conditions against the merged attributes
4. If conditions match, the automation action fires (e.g., send a template message)

**Example automation:** Send a template message when stage is "INTERESTED" and the lead's process is "RM".

Conditions:

| Property | Operator | Value      |
| -------- | -------- | ---------- |
| Stage    | equals   | INTERESTED |
| Process  | equals   | RM         |

This matches when:

* The disposition event has `stage = INTERESTED` (event attribute)
* The lead has `process = RM` (permanent attribute)

***

#### Scope (Entity Types)

A matcher can evaluate attributes from two entity types:

* **User** — the SalesChat user (agent/rep). Built-in properties: email, name. Custom attributes: any attributes set on the user (e.g., process, location, team).
* **Lead** — the contact/lead being communicated with. Built-in properties: phone number, first name, last name, CRM ID, stage, disposition. Custom attributes: any attributes set on the lead (e.g., campaign, product code).

You can scope a matcher to **User only**, **Lead only**, or **both**. The scope determines which properties are available when building conditions.

***

#### Properties

Properties are the fields you can evaluate in a condition. They come in two categories:

**Built-in properties**

These are always available:

| Property     | Entity Type | Description                              |
| ------------ | ----------- | ---------------------------------------- |
| Email        | User        | Agent's email address                    |
| Name         | User        | Agent's display name                     |
| Phone Number | Lead        | Lead's phone number                      |
| First Name   | Lead        | Lead's first name                        |
| Last Name    | Lead        | Lead's last name                         |
| CRM ID       | Lead        | Lead's CRM identifier                    |
| Stage        | Lead        | Lead's current stage (from events)       |
| Disposition  | Lead        | Lead's current disposition (from events) |

**Custom attributes**

Any attributes that have been set on users or leads in your organization appear automatically in the property dropdown. For example, if your CRM sync sets a `process` attribute on users, it will show up as a selectable property.

If the attribute you need isn't listed yet, you can manually add it by clicking **Add custom attribute** at the bottom of the property dropdown, selecting the entity type (User or Lead), and typing the attribute key.

**Event attributes** (like `call_time` or `payment_amount` sent via the disposition API) can also be used as custom attributes in matcher conditions.

***

#### Conditions and Condition Sets

**Conditions**

A condition is a single check: **property** + **operator** + **value**.

For example: *lead's stage* **equals** *"INTERESTED"*

**Condition Sets (AND + OR logic)**

Conditions are grouped into **Condition Sets**:

* Within a set, **all conditions must be true** (AND logic)
* Across sets, **any one set matching is enough** (OR logic)

```
Matcher passes if:
   (Set 1: ALL conditions true)    <- AND within
   OR                              <- OR across
   (Set 2: ALL conditions true)
   OR ...
```

**Example:** Trigger automation if the lead's stage is "INTERESTED" AND process is "RM", OR if the stage is "QUALIFIED" (regardless of process).

Set 1: `stage equals INTERESTED` AND `process equals RM` Set 2: `stage equals QUALIFIED`

***

#### Operator Reference

Operators define how a property's value is compared.

**Text matching**

| Operator            | Evaluation                                                                | Value input                       | Example                                  |
| ------------------- | ------------------------------------------------------------------------- | --------------------------------- | ---------------------------------------- |
| **equals**          | Passes if the actual value matches **any one** of the specified values    | One or more values (multi-select) | Stage equals "INTERESTED" or "QUALIFIED" |
| **not equals**      | Passes if the actual value does **not** match any of the specified values | One or more values (multi-select) | Disposition not equals "DND", "INVALID"  |
| **contains**        | Passes if the actual value contains the specified text as a substring     | Single value                      | Email contains "@saleschat"              |
| **doesn't contain** | Passes if the actual value does **not** contain the specified text        | Single value                      | Name doesn't contain "test"              |

**Numeric comparison**

| Operator         | Evaluation                                                                | Value input   | Example                          |
| ---------------- | ------------------------------------------------------------------------- | ------------- | -------------------------------- |
| **greater than** | Passes if the numeric value is strictly greater than the specified number | Single number | Payment amount greater than 5000 |
| **less than**    | Passes if the numeric value is strictly less than the specified number    | Single number | Call attempt number less than 3  |

> Non-numeric values are treated as 0 during numeric comparison.

**Presence checks**

| Operator       | Evaluation                                         | Value input   | Example             |
| -------------- | -------------------------------------------------- | ------------- | ------------------- |
| **is set**     | Passes if the attribute exists and has any value   | None required | Phone number is set |
| **is not set** | Passes if the attribute is missing or has no value | None required | CRM ID is not set   |

**Pattern matching**

| Operator          | Evaluation                                                             | Value input          | Example                 |
| ----------------- | ---------------------------------------------------------------------- | -------------------- | ----------------------- |
| **matches regex** | Passes if the actual value matches the full regular expression pattern | Single regex pattern | Phone matches `^\+91.*` |

> The regex must match the **entire** value, not just a part of it.

***

#### Example: Automation with Attribute Matcher

**Scenario:** Send a template message when a lead's disposition is updated to "INTERESTED" stage, but only for leads in the RM process with a policy number assigned.

**Condition Set 1:**

| Property                            | Operator | Value      |
| ----------------------------------- | -------- | ---------- |
| Stage (event attribute)             | equals   | INTERESTED |
| Process (permanent attribute)       | equals   | RM         |
| Policy Number (permanent attribute) | is set   | —          |

**Result:** When a disposition update event arrives with `stage = INTERESTED`, the matcher checks the event attribute (stage) and the lead's permanent attributes (process, policy\_number). If all conditions pass, the template message is sent.


# Apps on Saleschat

## What are External Apps?

External Apps let you send one-way messages to your leads through SalesChat from any external system — your CRM, marketing automation platform, notification service, or custom backend.

**Use cases:**

* Fyno / CleverTap / WebEngage sending campaign messages through SalesChat
* Your CRM triggering a follow-up template when a deal stage changes
* A custom backend sending appointment reminders or payment confirmations

**What External Apps can do:**

* Unified inbox — Messages sent from Fyno, CleverTap, or any external platform appear in the same agent inbox alongside regular conversations.
* Instant lead response — When a customer replies to a campaign or notification message, your sales agent sees it immediately and can respond in real-time. No switching between tools.
* Consistent customer experience — Whether a message originates from your CRM, notification platform, or SalesChat itself, the customer always sees it coming from your single WhatsApp business number.
* Audit trail — Every message sent through external apps is tracked with delivery status.
* The message appears in the chatroom as sent by the app's bot user, so agents can see it in context alongside their own messages.

> **Do I need to manage contact and chatroom?**\
> No. Contact and Chatroom are automatically resolved internally by Saleschat.


# Team Performance

Team Performance page is used to evaluate individual agent and the overall team's performance.

{% hint style="info" %}

## Update on 24th Oct 2025: We are rolling out Team Performance metrics and Delayed Response alerts as separate dashboard pages for our customers. If they are not yet activated for you it means that you are still on "old computation". Do reach out to us for early activation.

Only data from 1st July 2025 is available for the new Dashboards.
{% endhint %}

## Logic

1. All metrics are computed every 15 min.

> If "Today" is not activated for you then do reach out to us as we are rolling it out for our customers.

2. If message m1 was sent or received at time t1 while agent a1 was a participant and if the lead was reassigned to agent a2 at time t2 (after t1) then DO NOT consider message m1 for any metric for agent a2.
3. If message m1 was sent or received at time t1 while there were no agents in the chatroom, then that message is not attributed to any agent.

{% hint style="info" %}
**Logic for old computation**

If message m1 was sent or received at time t1 while there were no agents in the chatroom, then the conversations are attributed to the next agent that joins the chatroom, only if some agent joins the chatroom on the same day as such conversations. If no agent joins on the same day, then such conversations are not considered at all.
{% endhint %}

> **What about messages sent using campaign and automation?**
>
> Messages sent using campaign and automation are not attributed to any agent.

{% hint style="info" %}
**Logic for old computation**

Messages sent using campaign and automation features are considered as those being sent by the agent who is currently a participant for the purpose of analytics if and only if campaign and automation have chosen to send the message on behalf of the user.
{% endhint %}

> **What about messages in the chatroom that are not sent to or received from the lead?**
>
> Any state event within the chatroom, for ex. adding a participant or a nudge to the agent to respond back to the lead is NOT considered as a message for the purpose of agent performance analytics.

5. Any metric fetched for a time range or for a team is an aggregate of the daily metric calculated per agent.

> **What happens if the same agent talks to the same lead over two days?**
>
> If a lead l1 conversed with agent a1 over two days i.e. d1 and d2, then it will be counted as 2 unique conversations for agent a1 if both days fall within the selected date range.

> **What happens if the same lead talks to two agents on the same day?**
>
> If agent a1 and agent a2 belong to the same team and if lead l1 is reassigned from agent a1 to agent a2, then it will be attributed to each agent individually as well as counted as 2 conversations at the team level on that same day.

## Metrics

#### Unique Conversations

Count of all the leads, where there has been at least one message either sent or received, irrespective of the sender of the message, if the agent has been a participant of the chatroom while these messages were exchanged

#### Customer Responses

Count of all the leads, where the lead has responded at least once, if the agent has been a participant of that chatroom while these messages were received

#### Engagement Ratio

Division of Customer Responses / Unique Conversations

#### Delayed Response

Delayed response shows 90th percentile delay for the agent.

> Only greetings, question, task or a media messages that were sent by the lead are taken into consideration to calculate the delay in response.
>
> In case of consecutive messages from the lead, all of them fall into a single delayed response event until the agent responds.

> **Which delayed events are considered while calculating the delay?**
>
> The delayed response is calculated for both i.e. lead messages where the agent has not responded at all as well as where the agent has responded but after a delay of 15 min.

> **How do you handle out of office hours and no response from agents even on the next day while calculating the delay?**
>
> We exclude the configured office hours or default (i.e. 8pm to 8am) from delay calculation.

> **How do you handle delay computation when the agent has not even responded for 'n' days since the lead's message?**
>
> delay for an event is calculated only until midnight of that day.
>
> For ex. if the lead has messaged at 7pm and if out of office hours are from 1am to 6am, then delay will only be equal to 5 hours (12am - 7pm)

> **How do you handle delay computation if the room is reassigned to another agent?**
>
> Delay for an agent is computed only until the time that the agent was part of the room. If it is reassigned then the remaining delay time will be attributed to the reassigned agent.

#### Number of Attachment Sending Leads

Count of all the leads, where the lead has shared at least one media message, if the agent has been a participant of that chatroom on that day.

> Image, Video, PDF and any File is considered as a media message.
>
> Audio is not considered as a media message.

## Date Range

* Selecting "Today" will show you near real time data for today.
* Last 7 days does not include "Today"
* For Custom Date Range, Start Date is inclusive and End Date is exclusive.


# Metric Dumps

Describes all the metric dumps that are available on a Daily basis via Webhooks or Email

<table data-full-width="true"><thead><tr><th width="128">Metric Name</th><th width="102.4296875">Metric Version</th><th>File Formats</th><th width="128">Description</th><th>Webhook Group</th><th width="110.8203125">Webhook Version</th><th>Exportable from Dashboard</th><th>Deprecated</th></tr></thead><tbody><tr><td>Agent Metrics Dump</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/169dxCBk865TYSCCE59ICr0wpMP0Pa8sjvyjHL1SuJmI/edit?usp=drive_link">File Format</a></td><td>Agent's overall performance</td><td>ANALYTICS_DUMP_FILE with Metric Type AGENT_ANALYTICS</td><td>1.0 &#x26; 1.1</td><td>No</td><td>No</td></tr><tr><td>Campaign Analytics Dump</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1CzfdNRT4nAp3dRntTc8J7fCQMPXP92f0KFGMPrShi98/edit?usp=drive_link">File Format</a></td><td>Campaign's overall performance</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr><tr><td>Campaign Contact Summary Report</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1-XFJb3iEbjpY6kgdi-ouA9zted9N38zX-n0obBzh5V8/edit?usp=drive_link">File Format</a></td><td>Detail of each audience (lead) within the campaign</td><td>No</td><td>N/A</td><td>Yes</td><td>Yes</td></tr><tr><td>Campaign Audience Report</td><td></td><td><a href="https://docs.google.com/spreadsheets/d/1NdZnsF5lbB1_Jm7TsPU2zQjXQH4qSJ3jSMeEYE7JRYk/edit?usp=sharing">File Format</a></td><td>Detail of each audience (lead) within the campaign</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr><tr><td>Daily Message Dump</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1T42hxf6hbKU4OkmopfW-QBoBo5OlDBHp0ACRdfcUyNc/edit?usp=drive_link">File Format</a></td><td>All the chat interactions across all agents and leads</td><td>ANALYTICS_DUMP_FILE with Metric Type MESSAGE_DUMP</td><td>1.0</td><td>No</td><td>No</td></tr><tr><td></td><td>1.1</td><td><a href="https://docs.google.com/spreadsheets/d/1mpnNCfhekHmxhIDtyVQOmAAUbClZ_f_JRS2j-n9Tj8g/edit?usp=drive_link">File Format</a></td><td></td><td></td><td>1.1</td><td>No</td><td>No</td></tr><tr><td>Contact Summary Report</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1eleh1glxyz6EVLBpcO4tb-NzWxWWhn191RAQX4PeYXw/edit?usp=drive_link">File Format</a></td><td>Details of leads created on a given day</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr><tr><td>Automation Aggregate Report</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1SK3scsraAE0N6t7whQZvWzGkNXexsZGDng-BC25qxCo/edit?usp=drive_link">File Format</a></td><td>Automation's overall performance</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr><tr><td>Automation Execution Audit Report</td><td></td><td><a href="https://docs.google.com/spreadsheets/d/17N2tTZqAsYcL6Ix2Sm-lr8p14p4sYYZBElS8ldZrwnI/edit?usp=sharing">File Format</a></td><td>Detail of each execution for an automation</td><td>No</td><td>N/A</td><td>Yes</td><td>Yes</td></tr><tr><td>CSAT Aggregate Report</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/15pzPxtzFpswtaGgCfrsN97WGuMzQD5wYh85mI0oEFjc/edit?usp=drive_link">File Format</a></td><td>CSAT's overall performance</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr><tr><td>CSAT Records</td><td>1.0</td><td><a href="https://docs.google.com/spreadsheets/d/1Afz8pdIJsiMtYYHfFgnKctqrAJ-HtY9xR-nibwYA5_0/edit?usp=drive_link">File Format</a></td><td>CSAT details per lead</td><td>No</td><td>N/A</td><td>No</td><td>No</td></tr></tbody></table>


# Rate Limit

All our APIs have rate limits. On reaching the rate limit threshold, an API will respond withHTTP status code 429 TOO MANY REQUESTS

## Global Rate Limits

### Rate Limit Per Org ID and Per Endpoint

Any API endpoint that has `{orgId}` in the path will be subject to this rate limit.

### Rate Limit Per User

Any API that is accessible after login is subject to this rate limit.

### Summary Table

<table><thead><tr><th width="342">Key</th><th data-type="number">Requests Allowed</th><th data-type="number">Per Seconds</th></tr></thead><tbody><tr><td><code>{orgId}+{endpoint}</code></td><td>10</td><td>1</td></tr><tr><td><code>{orgId}+{userId}+{endpoint}</code></td><td>5</td><td>1</td></tr></tbody></table>

## Specific Rate Limits

There are some API endpoints which have additional (stricter) rate limit.

### Lead Assign API

API endpoints have stricter rate limit of 1 request per 10 seconds per lead.

<table><thead><tr><th>Endpoint</th><th width="346">Path</th><th width="151" data-type="number">Requests Allowed</th><th data-type="number">Per Seconds</th></tr></thead><tbody><tr><td>v3 Assign (Deprecated)</td><td><code>/v3/orgs/{orgId}/contacts/{contactId}/assign</code></td><td>1</td><td>10</td></tr><tr><td>v4 Assign</td><td><code>/v4/orgs/{orgId}/leads/{leadId}/assign</code></td><td>1</td><td>10</td></tr></tbody></table>


# User

This page provides APIs to manage users in Saleschat, including adding users, resetting passwords, generating magic links, and fetching user details.

## Create a user and add it to the org

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> ask\_user\_to\_update\_password\_on\_login: Default value is False \</li>\<li> emailConfirmed: User's email will be considered to be confirmed \</li>\<li> Email to confirm email will not be sent \</li>\<li> Role of the user added will be Member \</li>\<li> Sometimes a user may be created without being added to the org and will have to be handled manually \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CreateUserReqDto":{"required":["email","first_name","last_name","password"],"type":"object","properties":{"email":{"maxLength":319,"minLength":0,"type":"string"},"password":{"maxLength":64,"minLength":8,"type":"string"},"ask_user_to_update_password_on_login":{"type":"boolean"},"first_name":{"maxLength":40,"minLength":0,"type":"string"},"last_name":{"maxLength":40,"minLength":0,"type":"string"}}},"CreateUserRespDto":{"type":"object","properties":{"user_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user":{"post":{"tags":["user-controller"],"summary":"Create a user and add it to the org","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> ask_user_to_update_password_on_login: Default value is False </li><li> emailConfirmed: User's email will be considered to be confirmed </li><li> Email to confirm email will not be sent </li><li> Role of the user added will be Member </li><li> Sometimes a user may be created without being added to the org and will have to be handled manually </li></ul>","operationId":"createUserAndAddToOrg","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserReqDto"}}},"required":true},"responses":{"200":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden: Unauthorized access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Reset a users password

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: True \</li>\<li> User will be required to reset the password on next login \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"UserPasswordReqDto":{"required":["password"],"type":"object","properties":{"password":{"type":"string"},"ask_user_to_update_password_on_login":{"type":"boolean"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user/{userId}/password/reset":{"post":{"tags":["user-controller"],"summary":"Reset a users password","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: True </li><li> Partner Allowed: True </li><li> User will be required to reset the password on next login </li></ul>","operationId":"resetPassword","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPasswordReqDto"}}},"required":true},"responses":{"204":{"description":"Successfully reset"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"UserId does not exist for this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Generate a magic link for a user

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"MagicLinkRespDto":{"type":"object","properties":{"url":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user/{userId}/magiclink":{"get":{"tags":["user-controller"],"summary":"Generate a magic link for a user","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li></ul>","operationId":"generateMagicLink","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully generated magic link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"UserId does not exist for this org or user has been deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Get user by email

> \<ul>\<li>Roles Allowed: MEMBER\</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: True \</li>\<li> Supports Partial match on email ID\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"PaginatedItemGetUserRespDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/GetUserRespDto"}},"has_more":{"type":"boolean"}}},"GetUserRespDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user":{"get":{"tags":["user-controller"],"summary":"Get user by email","description":"<ul><li>Roles Allowed: MEMBER</li><li> Impersonated User Allowed: True </li><li> Partner Allowed: True </li><li> Supports Partial match on email ID</li></ul>","operationId":"getUserListByEmail","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"q","in":"query","required":true,"schema":{"type":"string","default":""}},{"name":"offset","in":"query","required":false,"schema":{"minimum":0,"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"minimum":0,"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"Successfully fetched user for email ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedItemGetUserRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Delete a user

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li>Partner Allowed: True\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user/{userId}/delete":{"post":{"tags":["user-controller"],"summary":"Delete a user","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li>Partner Allowed: True</li></ul>","operationId":"deleteUser","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"User Id does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Disable a user

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li>Partner Allowed: True\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user/{userId}/disable":{"post":{"tags":["user-controller"],"summary":"Disable a user","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li>Partner Allowed: True</li></ul>","operationId":"disableUser","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully disabled"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"userId does not exist for this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Enable a user

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li>Partner Allowed: True\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/user/{userId}/enable":{"post":{"tags":["user-controller"],"summary":"Enable a user","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li>Partner Allowed: True</li></ul>","operationId":"enableUser","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully enabled"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"userId does not exist for this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```


# Leads

This page provides API documentation for creating a lead in Saleschat.pro, including the required parameters and sample responses for successful lead creation.

## Create a new lead for the specified organization

> Creates a new lead with the provided details. The request must include either a valid bearer token or an x-org-api-key for authentication. The response will contain the details of the created lead.

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CreateLeadV4Request":{"required":["attributes","crm_id","first_name","phone_number"],"type":"object","properties":{"crm_id":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"object"}},"phone_number":{"type":"string"},"opt_in_date":{"type":"integer","format":"int64"}}},"CreateLeadV4Response":{"type":"object","properties":{"lead_id":{"type":"string"},"crm_id":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"object"}},"phone_number":{"type":"string"},"opt_in_date":{"type":"integer","format":"int64"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v4/orgs/{orgId}/leads":{"post":{"tags":["Leads"],"summary":"Create a new lead for the specified organization","description":"Creates a new lead with the provided details. The request must include either a valid bearer token or an x-org-api-key for authentication. The response will contain the details of the created lead.","operationId":"createLead","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadV4Request"}}},"required":true},"responses":{"200":{"description":"Successfully created lead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadV4Response"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Org not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"429":{"description":"Lead with this crm_id already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to create lead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Assign a lead to a user

> Assigns the specified lead to a user. The request must include either a valid bearer token or an x-org-api-key for authentication. The request body should contain either the ID or the email of the user to assign the lead to.

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AssignLeadRequest":{"type":"object","properties":{"user_id":{"type":"string"},"user_email":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v4/orgs/{orgId}/leads/{leadId}/assign":{"put":{"tags":["Leads"],"summary":"Assign a lead to a user","description":"Assigns the specified lead to a user. The request must include either a valid bearer token or an x-org-api-key for authentication. The request body should contain either the ID or the email of the user to assign the lead to.","operationId":"assign","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"leadId","in":"path","description":"Saleschat-generated lead ID (UUID) or the lead's CRM ID — both are resolved.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignLeadRequest"}}},"required":true},"responses":{"202":{"description":"Successfully assigned lead"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Org or lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to assign lead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Add an event for a lead

> Records a custom event for the specified lead. If the event type matches a known automation trigger it will be enqueued for processing. Uses distinct\_id for idempotency — duplicate requests with the same distinct\_id are silently accepted.

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CreateLeadEventRequest":{"required":["event"],"type":"object","properties":{"distinct_id":{"maxLength":36,"minLength":0,"type":"string","description":"Optional idempotency key. Empty or whitespace-only values are treated as having no value at all (no deduplication is performed); otherwise surrounding whitespace is stripped."},"event":{"maxLength":128,"minLength":0,"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"object"}}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v4/orgs/{orgId}/leads/{leadId}/events":{"put":{"tags":["Leads"],"summary":"Add an event for a lead","description":"Records a custom event for the specified lead. If the event type matches a known automation trigger it will be enqueued for processing. Uses distinct_id for idempotency — duplicate requests with the same distinct_id are silently accepted.","operationId":"createLeadEvent","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"leadId","in":"path","description":"Saleschat-generated lead ID (UUID) or the lead's CRM ID — both are resolved.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadEventRequest"}}},"required":true},"responses":{"202":{"description":"Event accepted"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Org or lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to process event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Look up a lead by CRM ID

> Translates a CRM ID into the Saleschat lead ID, returning the lead\_id/crm\_id pair. Responds 404 when no live lead or contact exists for the CRM ID, including when the matched contact has been expired. Note: a matched legacy contact is promoted to a lead on first access, so this endpoint is not side-effect-free and must not be cached.

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"LeadCrmLookupResponse":{"type":"object","properties":{"lead_id":{"type":"string"},"crm_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v4/orgs/{orgId}/leads/lookup":{"get":{"tags":["Leads"],"summary":"Look up a lead by CRM ID","description":"Translates a CRM ID into the Saleschat lead ID, returning the lead_id/crm_id pair. Responds 404 when no live lead or contact exists for the CRM ID, including when the matched contact has been expired. Note: a matched legacy contact is promoted to a lead on first access, so this endpoint is not side-effect-free and must not be cached.","operationId":"lookupLeadByCrmId","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"crm_id","in":"query","description":"The lead's CRM ID. A Saleschat lead ID (UUID) also resolves. Percent-encode reserved characters — in particular a leading '+' on an E.164 phone number should be sent as %2B (a raw '+' decodes to a space in a query string, though that common case is recovered server-side).","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Lead found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadCrmLookupResponse"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Org not found, or no live lead for crm_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Missing or invalid crm_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to look up lead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```


# Attributes

This page provides API documentation for performing operations on Dynamic Attributes.

## Partially update (merge) dynamic attributes for an entity

> \<p>\<b>Access Control:\</b>\</p>\
> \<ul>\
> &#x20; \<li>\<b>Allowed Roles:\</b> MEMBER\</li>\
> &#x20; \<li>\<b>Impersonated User Allowed:\</b> No\</li>\
> &#x20; \<li>\<b>Organization API Key Allowed:\</b> Yes\</li>\
> \</ul>\
> \
> \<p>\<b>Patch Behavior:\</b>\</p>\
> \<ul>\
> &#x20; \<li>\<b>Attribute not present in request:\</b> A new attribute will be created.\</li>\
> &#x20; \<li>\<b>Attribute set to null:\</b> The request will fail because the attribute has a non-null validation constraint.\</li>\
> &#x20; \<li>\<b>Attribute set to an empty object ({ }):\</b> No changes will be applied.\</li>\
> \</ul><br>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"PatchDynamicAttributeRequest":{"required":["attributes"],"type":"object","properties":{"attributes":{"type":"object","additionalProperties":{"type":"object"}}}},"DynamicAttributeResponse":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"org_id":{"type":"string"},"entity_type":{"type":"string"},"entity_id":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"object"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v4/orgs/{orgId}/dynamic-attributes/{entityType}/{entityId}":{"patch":{"tags":["Dynamic Attributes"],"summary":"Partially update (merge) dynamic attributes for an entity","description":"<p><b>Access Control:</b></p>\n<ul>\n  <li><b>Allowed Roles:</b> MEMBER</li>\n  <li><b>Impersonated User Allowed:</b> No</li>\n  <li><b>Organization API Key Allowed:</b> Yes</li>\n</ul>\n\n<p><b>Patch Behavior:</b></p>\n<ul>\n  <li><b>Attribute not present in request:</b> A new attribute will be created.</li>\n  <li><b>Attribute set to null:</b> The request will fail because the attribute has a non-null validation constraint.</li>\n  <li><b>Attribute set to an empty object ({ }):</b> No changes will be applied.</li>\n</ul>\n","operationId":"patchAttributes","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"entityType","in":"path","required":true,"schema":{"type":"string"}},{"name":"entityId","in":"path","description":"Entity ID. For entity type 'lead', accepts either the Saleschat-generated lead ID (UUID) or the lead's CRM ID. For other entity types, the exact entity ID is required.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchDynamicAttributeRequest"}}},"required":true},"responses":{"200":{"description":"Successfully patched attributes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicAttributeResponse"}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Unauthorized access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Unknown entity type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Partially update (merge) dynamic attributes for an entity

> \<p>\<b>Access Control:\</b>\</p>\
> \<ul>\
> &#x20; \<li>\<b>Allowed Roles:\</b> MEMBER\</li>\
> &#x20; \<li>\<b>Impersonated User Allowed:\</b> No\</li>\
> &#x20; \<li>\<b>Organization API Key Allowed:\</b> Yes\</li>\
> \</ul>\
> \
> \<p>\<b>Patch Behavior:\</b>\</p>\
> \<ul>\
> &#x20; \<li>\<b>Attribute not present in request:\</b> A new attribute will be created.\</li>\
> &#x20; \<li>\<b>Attribute set to null:\</b> The request will fail because the attribute has a non-null validation constraint.\</li>\
> &#x20; \<li>\<b>Attribute set to an empty object ({ }):\</b> No changes will be applied.\</li>\
> \</ul><br>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"PatchDynamicAttributeRequest":{"required":["attributes"],"type":"object","properties":{"attributes":{"type":"object","additionalProperties":{"type":"object"}}}},"DynamicAttributeResponse":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"org_id":{"type":"string"},"entity_type":{"type":"string"},"entity_id":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"object"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/orgs/{orgId}/dynamic-attributes/{entityType}/{entityId}":{"patch":{"tags":["dynamic-attribute-controller"],"summary":"Partially update (merge) dynamic attributes for an entity","description":"<p><b>Access Control:</b></p>\n<ul>\n  <li><b>Allowed Roles:</b> MEMBER</li>\n  <li><b>Impersonated User Allowed:</b> No</li>\n  <li><b>Organization API Key Allowed:</b> Yes</li>\n</ul>\n\n<p><b>Patch Behavior:</b></p>\n<ul>\n  <li><b>Attribute not present in request:</b> A new attribute will be created.</li>\n  <li><b>Attribute set to null:</b> The request will fail because the attribute has a non-null validation constraint.</li>\n  <li><b>Attribute set to an empty object ({ }):</b> No changes will be applied.</li>\n</ul>\n","operationId":"patchAttributes_1","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"entityType","in":"path","required":true,"schema":{"type":"string"}},{"name":"entityId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchDynamicAttributeRequest"}}},"required":true},"responses":{"200":{"description":"Successfully patched attributes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicAttributeResponse"}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Unauthorized access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```


# Media

This page provides API documentation for uploading/dowloading media from Saleschat.pro securely.

## Get Signed URL to download a file

> \<ul>\<li>Roles Allowed: Member and Partner\</li>\<li>Impersonated User Allowed: True\</li>\<li>fileId is the id of file record\</li>\<li>Use response signedUrl as follows: curl -X GET '${url}'\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"FileRespDto":{"type":"object","properties":{"signed_url":{"type":"string"},"file_id":{"type":"string"},"file_upload_name":{"type":"string"},"mime_type":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/orgs/{orgId}/file/{fileId}/download/signed_url":{"get":{"tags":["file-controller"],"summary":"Get Signed URL to download a file","description":"<ul><li>Roles Allowed: Member and Partner</li><li>Impersonated User Allowed: True</li><li>fileId is the id of file record</li><li>Use response signedUrl as follows: curl -X GET '${url}'</li></ul>","operationId":"getDownloadSignedUrl","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully fetched signed download url","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileRespDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or partner not allowed to download file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```


# Apps

This page provides API documentation for sending WABA template messages in Saleschat.pro, including required parameters and template validation rules for successful message delivery via Apps.

## POST /v2/apps/send

>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"paths":{"/v2/apps/send":{"post":{"tags":["apps-send-controller"],"operationId":"send","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonNode"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSendResponse"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}},"components":{"schemas":{"JsonNode":{"type":"object"},"AppSendResponse":{"type":"object","properties":{"request_id":{"type":"string"},"status":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}}}
```

#### Authentication

Include your API key in the `x-api-key` header:

```
x-api-key: sc_rest_a1b2c3d4e5f6...
```

The API key can be generated from the dashboard for an External App. It identifies both your app and your organisation — no need to pass an org ID.

Note: The App API key is separate from Org API Key.

#### Request Format

```json
{
   "messaging_product":"whatsapp",
   "to":"+919876543210",
   "type":"template",
   "template":{
      "name":"appointment_reminder",
      "language":{
         "policy":"deterministic",
         "code":"en"
      },
      "components":[
         {
            "type":"body",
            "parameters":[
               {
                  "type":"text",
                  "text":"Rahul"
               },
               {
                  "type":"text",
                  "text":"March 25, 2026"
               },
               {
                  "type":"text",
                  "text":"10:00 AM"
               }
            ]
         }
      ]
   }
}
```


# Mutual TLS

Saleschat Mutual TLS allows organizations to configure an additional layer of security for their Saleschat API traffic.\
\
Once configured, API requests should be made to [https://mtls.apis.saleschat.pro](https://mtls.apis.saleschat.pro/) (or [https://mtls.apis.t.saleschat.pro](https://mtls.apis.t.saleschat.pro/) for UAT environment) and traffic will only be accepted if the right API key and client certificate are provided.\
\
mTLS does not apply to the normal TLS domain, [https://apis.saleschat.pro](https://apis.saleschat.pro/) or [https://apis.t.saleschat.pro](https://apis.t.saleschat.pro/).

#### Customer-Owned Certificate Model

Saleschat uses a Bring Your Own Certificate (BYOC) Model.

In this model -

* Enterprise generates and owns the private key.
* Enterprise generates the client certificate.
* Enterprise shares only the public certificate with Saleschat.
* Saleschat registers and trusts the certificate.
* Enterprise uses the private key locally to establish mTLS connections.

{% hint style="warning" %}
The private key must never be shared with Saleschat.
{% endhint %}

#### Certificate Requirements

| Setting             | Recommended Value |
| ------------------- | ----------------- |
| Key Type            | RSA               |
| Key Size            | 2048 or 4096      |
| Signature Algorithm | SHA256            |
| Validity            | 1 year            |

#### How to generate the certificate?

Run this command on a secure machine/server.

```shellscript
openssl genrsa -out saleschat-client.key 2048
```

Generated file will be -

```
saleschat-client.key
```

{% hint style="info" %}
This is a sensitive file. Store it securely, do not share it with Saleschat or anyone outside your organization.
{% endhint %}

Set the permission for the file -

```shellscript
chmod 600 saleschat-client.key
```

Run the following to generate the client certificate -

```shellscript
openssl req -x509 -new \
  -key saleschat-client.key \
  -out saleschat-client.crt \
  -days 365 \
  -sha256 \
  -subj "/C=IN/ST=Maharashtra/L=Mumbai/O=${YOUR_COMPANY}/OU=Technology/CN=${YOUR_COMPANY}-saleschat-mtls"
```

{% hint style="info" %}
Subject is optional, and you can replace ${YOUR\_COMPANY} with your company name in format. This has got nothing to do with the client or server domain.
{% endhint %}

Generated file will be -

```
saleschat-client.crt
```

#### How do I setup mTLS integration?

On the settings page, you'll see 'mTLS' tab on the left navigation bar

<figure><img src="/files/3EQ22XOQlQTk3J89xZFb" alt=""><figcaption></figcaption></figure>

Click on the 'Upload Certificate' button.\
\ <img src="/files/RLfaSNUySoABD6OYM5lm" alt="" data-size="original">

You can either upload the X.509 public certificate file, or copy and paste the contents of the file. Click on upload and the certificate would be applicable.\
\
You can then use the [https://mtls.apis.saleschat.pro](https://mtls.apis.saleschat.pro/) (or UAT) domain to make API requests.

#### How to test if the certificate is working?

Use the following CURL to verify if you've configured the certificate correctly

```shellscript
curl -i \
  --cert saleschat-client.crt \
  --key saleschat-client.key \
  "https://mtls.apis.saleschat.pro/v4/orgs/<ORG_ID>/mtls/hello"
```

You should `200 OK` response with the following text -

```
HTTP/2 200 
date: Mon, 08 Jun 2026 08:13:55 GMT
content-type: text/plain;charset=ISO-8859-1
content-length: 13

Hello, world!
```


# Contact (Deprecated)

This page provides API documentation for creating a contact in Saleschat.pro, including the required parameters and sample responses for successful contact creation.

{% hint style="warning" %}
Contact APIs are being deprecated and Saleschat will stop supporting it from Sept 1st, 2026.\
Kindly use the [Leads](/api-documentation/leads) documentation.
{% endhint %}

## Create a contact

> \<ul>\<li>Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> Error Codes : Error Message \</li>\<ol> 4030001 : FORBIDDEN \</ol>\<ol> 4090001 : UQ\_CONSTRAINT\_FAILED \</ol>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ContactReqDto":{"required":["crm_id","opt_in_date","phone_number"],"type":"object","properties":{"crm_id":{"maxLength":128,"minLength":0,"type":"string"},"phone_number":{"$ref":"#/components/schemas/PhoneNumber"},"opt_in_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"first_name":{"maxLength":128,"minLength":0,"pattern":"^(?!.*\\*).*$","type":"string"},"last_name":{"maxLength":128,"minLength":0,"pattern":"^(?!.*\\*).*$","type":"string"},"governance_level_id":{"maxLength":128,"minLength":0,"type":"string"},"is_inbound":{"type":"boolean"},"source":{"type":"string","enum":["BTRIX","CAMPAIGN"]}}},"PhoneNumber":{"type":"object","properties":{"extension":{"type":"string"},"countryCode":{"type":"integer","format":"int32"},"nationalNumber":{"type":"integer","format":"int64"},"italianLeadingZero":{"type":"boolean"},"rawInput":{"type":"string"},"preferredDomesticCarrierCode":{"type":"string"},"countryCodeSource":{"type":"string","enum":["FROM_NUMBER_WITH_PLUS_SIGN","FROM_NUMBER_WITH_IDD","FROM_NUMBER_WITHOUT_PLUS_SIGN","FROM_DEFAULT_COUNTRY","UNSPECIFIED"]},"numberOfLeadingZeros":{"type":"integer","format":"int32"}},"description":"e164 format"},"ContactRespDto":{"type":"object","properties":{"id":{"type":"string"},"crm_id":{"type":"string"},"opt_in_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"create_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"governance_level":{"$ref":"#/components/schemas/GovernanceLevelDto"},"is_expired":{"type":"boolean"}}},"GovernanceLevelDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v2/org/{orgId}/contact":{"post":{"tags":["contact-controller"],"summary":"Create a contact","description":"<ul><li>Roles Allowed: ADMIN</li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> Error Codes : Error Message </li><ol> 4030001 : FORBIDDEN </ol><ol> 4090001 : UQ_CONSTRAINT_FAILED </ol></ul>","operationId":"registerContactV2","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactReqDto"}}},"required":true},"responses":{"200":{"description":"Successfully registered contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or Partner is not allowed to create a contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"409":{"description":"Conflicting entry in DB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Invalid format or bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Assign a contact to a user

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> API will assign a contact to a user or a group from which the user can be selected. Only one of them is required, if both are provided, user\_id will be used\</li>\<li> assign\_on\_handover is a boolean flag to indicate if the user should be assigned to the chatroom after the lead has responded\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AssignChatroomReqDto":{"type":"object","properties":{"user_id":{"type":"string"},"group_id":{"type":"string"},"remote_waba_id":{"type":"string"},"remote_phone_id":{"type":"string"},"assign_on_handover":{"type":"boolean"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v3/orgs/{orgId}/contacts/{contactId}/assign":{"post":{"tags":["chatroom-controller"],"summary":"Assign a contact to a user","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> API will assign a contact to a user or a group from which the user can be selected. Only one of them is required, if both are provided, user_id will be used</li><li> assign_on_handover is a boolean flag to indicate if the user should be assigned to the chatroom after the lead has responded</li></ul>","operationId":"assignChatroom","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignChatroomReqDto"}}},"required":true},"responses":{"202":{"description":"User will be assigned to the room"},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Cannot make this request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"User / Group not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"429":{"description":"Rate limit exceeded. Allows 1 request per 10 seconds per contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Update a contact

> \<ul>\<li> Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: FALSE \</li>\<li> Partner Allowed: TRUE\</li>\<li> Update contact crmID, first name, last name and chatroom name will be automatically updated \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"UpdateContactReqDto":{"required":["crm_id"],"type":"object","properties":{"crm_id":{"maxLength":128,"minLength":0,"type":"string"},"first_name":{"maxLength":128,"minLength":0,"pattern":"^(?!.*\\*).*$","type":"string"},"last_name":{"maxLength":128,"minLength":0,"pattern":"^(?!.*\\*).*$","type":"string"}}},"ContactRespDto":{"type":"object","properties":{"id":{"type":"string"},"crm_id":{"type":"string"},"opt_in_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"create_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"governance_level":{"$ref":"#/components/schemas/GovernanceLevelDto"},"is_expired":{"type":"boolean"}}},"GovernanceLevelDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/orgs/{orgId}/contact/{contactId}":{"put":{"tags":["contact-controller"],"summary":"Update a contact","description":"<ul><li> Roles Allowed: ADMIN</li><li> Impersonated User Allowed: FALSE </li><li> Partner Allowed: TRUE</li><li> Update contact crmID, first name, last name and chatroom name will be automatically updated </li></ul>","operationId":"updateContact","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactReqDto"}}},"required":true},"responses":{"200":{"description":"Successfully updated contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRespDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User does not belong to org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Contact not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to update contact due to internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Update disposition & stage for a contact

> \<ul>\<li> Roles Allowed: ADMIN\</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: TRUE\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"UpdateContactDispositionReqV2Dto":{"required":["stage"],"type":"object","properties":{"additionalAttributes":{"type":"object","additionalProperties":{"type":"string"}},"stage":{"type":"string"},"disposition":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v2/orgs/{orgId}/contact/{contactId}/disposition":{"put":{"tags":["contact-controller"],"summary":"Update disposition & stage for a contact","description":"<ul><li> Roles Allowed: ADMIN</li><li> Impersonated User Allowed: True </li><li> Partner Allowed: TRUE</li></ul>","operationId":"updateContactDispositionV2","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactDispositionReqV2Dto"}}},"required":true},"responses":{"200":{"description":"Successfully updated contact disposition","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User does not belong to org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Contact not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to add contact disposition due to internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Get Contact by Phone Number

> \<ul>\<li>Roles Allowed: MEMBER\</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: True \</li>\<li> PhoneNumber should be in E164 format \</li>\<li> The result will contain all contacts for a given pn.\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GetContactRespDto":{"type":"object","properties":{"id":{"type":"string"},"crm_id":{"type":"string"},"opt_in_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"create_date":{"type":"string","description":"epoch in seconds","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v2/org/{orgId}/contact/pn/{phoneNumber}":{"get":{"tags":["contact-controller"],"summary":"Get Contact by Phone Number","description":"<ul><li>Roles Allowed: MEMBER</li><li> Impersonated User Allowed: True </li><li> Partner Allowed: True </li><li> PhoneNumber should be in E164 format </li><li> The result will contain all contacts for a given pn.</li></ul>","operationId":"getContactByPhoneV2","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"phoneNumber","in":"path","description":"e164 format","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully responding with list of all contacts for a pn","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GetContactRespDto"}}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Phone Number not in the correct format or required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Server Error - Something went wrong on the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```


# Chatroom (Deprecated)

This page outlines the API documentation for creating, managing, reassigning, and activating/deactivating chatrooms in Saleschat.pro.

{% hint style="warning" %}
Chatroom APIs are being deprecated and Saleschat will stop supporting it from Sept 1st, 2026.\
Kindly use the [Leads](/api-documentation/leads) documentation.
{% endhint %}

## Create a new chatroom for a lead V3

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> leadId is the id field in contact table \</li>\<li> API will create a chatroom or return an existing chatroom for this contact \</li>\<li> Chatroom will be created for the provided Waba and the Phone number if they are registered for this org \</li>\<li> Chatroom's display name will be display name if provided \</li>\<li> Otherwise Chatroom's display name will be contact's crm\_id + FN + LN \</li>\<li> After a certain thresold number of days of inactivity a chatroom is Deactivated. After Deactivation of chatroom, a new chatroom for the same contact with a different crmId can be created\</li>\<li> After a certain thresold number of days of creation a chatroom is Expired. After Expiry of chatroom, a new chatroom for the same contact with a different crmId can be created\</li>\<li> At any point of time only one active chatroom (not deactivated & not expired) can exist for a unique phone number\</li>\<li> On every chatroom creation, a new contact-waba is created if not already present \</li>\<li> Each contact can only have one waba mapping\</li>\<li> Every contact-waba mapping is per Waba per Waba Phone, i.e any contact with same phone can one active chatroom present across multiple Waba Phone(s)\</li>\<li> By default (fail\_if\_chatroom\_exists\_on\_other\_wabaphone = true), in case of an existing contact-waba mapping, we throw a Conflict upon trying to create a chatroom for the same phone number.\</li>\<li> For fail\_if\_chatroom\_exists\_on\_other\_wabaphone = false, we create chatroom with same phone number with the next available Waba Phone.\</li>\<li> This API allows chatroom handover, that is, that the agent will only be assigned to chatroom after the lead has responded\</li>\<li> Assignment of this chatroom can be done by specifying a user or a group from which the user can be selected\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CreateChatroomReqV3Dto":{"required":["assign_details","lead_id"],"type":"object","properties":{"lead_id":{"type":"string"},"display_name":{"type":"string","deprecated":true},"remote_waba_id":{"type":"string"},"remote_phone_id":{"type":"string"},"force_deactivate":{"type":"boolean","description":"When this option is set to true, then all the existing chatrooms for the lead will be deactivated and a new chatroom would be created.","default":false},"fail_if_chatroom_exists_on_other_waba_phone":{"type":"boolean","description":"If set to true, the request will fail if a chatroom already exists on a different WABA phone.","default":true},"assign_details":{"$ref":"#/components/schemas/ChatroomAssignmentDetailsDto"}}},"ChatroomAssignmentDetailsDto":{"required":["assign_mode"],"type":"object","properties":{"assign_mode":{"type":"string","enum":["USER","GROUP","DELEGATE"]},"user_id":{"type":"string","description":"User ID to assign the chatroom to. Either user_id or user_email is required when assign_mode is USER."},"user_email":{"type":"string","description":"User Email to assign the chatroom to. Either user_id or user_email is required when assign_mode is USER."},"group_id":{"type":"string","description":"Group ID to assign the chatroom to. Required when assign_mode is GROUP."},"assign_on_handover":{"type":"boolean","description":"Whether to assign the chatroom on handover","default":false}}},"ChatroomRespDto":{"type":"object","properties":{"chatroom_id":{"type":"string"},"external_ref_id":{"type":"string"},"is_existing":{"type":"boolean"},"is_deactivated":{"type":"boolean"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"},"deactivation_ts":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v3/org/{orgId}/lead/chatroom":{"post":{"tags":["chatroom-controller"],"summary":"Create a new chatroom for a lead V3","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> leadId is the id field in contact table </li><li> API will create a chatroom or return an existing chatroom for this contact </li><li> Chatroom will be created for the provided Waba and the Phone number if they are registered for this org </li><li> Chatroom's display name will be display name if provided </li><li> Otherwise Chatroom's display name will be contact's crm_id + FN + LN </li><li> After a certain thresold number of days of inactivity a chatroom is Deactivated. After Deactivation of chatroom, a new chatroom for the same contact with a different crmId can be created</li><li> After a certain thresold number of days of creation a chatroom is Expired. After Expiry of chatroom, a new chatroom for the same contact with a different crmId can be created</li><li> At any point of time only one active chatroom (not deactivated & not expired) can exist for a unique phone number</li><li> On every chatroom creation, a new contact-waba is created if not already present </li><li> Each contact can only have one waba mapping</li><li> Every contact-waba mapping is per Waba per Waba Phone, i.e any contact with same phone can one active chatroom present across multiple Waba Phone(s)</li><li> By default (fail_if_chatroom_exists_on_other_wabaphone = true), in case of an existing contact-waba mapping, we throw a Conflict upon trying to create a chatroom for the same phone number.</li><li> For fail_if_chatroom_exists_on_other_wabaphone = false, we create chatroom with same phone number with the next available Waba Phone.</li><li> This API allows chatroom handover, that is, that the agent will only be assigned to chatroom after the lead has responded</li><li> Assignment of this chatroom can be done by specifying a user or a group from which the user can be selected</li></ul>","operationId":"createChatroomV3","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChatroomReqV3Dto"}}},"required":true},"responses":{"200":{"description":"Successfully created the chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatroomRespDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or Partner does not have access to this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Waba does not exist / WabaPhone does not exist / User or group does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"409":{"description":"Active chatroom already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Reassign Chatroom V3

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> This API works only for chatrooms created for waba. Hence explicitly added /waba in the API endpoint \</li>\<li> API will revoke access of all the existing users from the chatroom and add new users to the chatroom \</li>\<li> Depending on the room history visibility flag while creating the chatroom the new users may or may not see messages from the past \</li>\<li> This API allows chatroom handover, that is, that the agent will only be assigned to chatroom after the lead has responded\</li>\<li> Reassignment of this chatroom can be done by specifying a user or a group from which the user can be selected\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ChatroomReassignReqV3Dto":{"required":["assign_details"],"type":"object","properties":{"assign_details":{"$ref":"#/components/schemas/ChatroomAssignmentDetailsDto"}}},"ChatroomAssignmentDetailsDto":{"required":["assign_mode"],"type":"object","properties":{"assign_mode":{"type":"string","enum":["USER","GROUP","DELEGATE"]},"user_id":{"type":"string","description":"User ID to assign the chatroom to. Either user_id or user_email is required when assign_mode is USER."},"user_email":{"type":"string","description":"User Email to assign the chatroom to. Either user_id or user_email is required when assign_mode is USER."},"group_id":{"type":"string","description":"Group ID to assign the chatroom to. Required when assign_mode is GROUP."},"assign_on_handover":{"type":"boolean","description":"Whether to assign the chatroom on handover","default":false}}},"ChatroomRespDto":{"type":"object","properties":{"chatroom_id":{"type":"string"},"external_ref_id":{"type":"string"},"is_existing":{"type":"boolean"},"is_deactivated":{"type":"boolean"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"},"deactivation_ts":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v3/org/{orgId}/lead/chatroom/{chatroomId}/reassign":{"post":{"tags":["reassignment-controller"],"summary":"Reassign Chatroom V3","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> This API works only for chatrooms created for waba. Hence explicitly added /waba in the API endpoint </li><li> API will revoke access of all the existing users from the chatroom and add new users to the chatroom </li><li> Depending on the room history visibility flag while creating the chatroom the new users may or may not see messages from the past </li><li> This API allows chatroom handover, that is, that the agent will only be assigned to chatroom after the lead has responded</li><li> Reassignment of this chatroom can be done by specifying a user or a group from which the user can be selected</li></ul>","operationId":"reassignChatroomV3","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"chatroomId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatroomReassignReqV3Dto"}}},"required":true},"responses":{"200":{"description":"Successfully re-assigned the chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatroomRespDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or Partner does not have access to this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Chatroom does not exist for this org / OrgId does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"429":{"description":"Rate limit exceeded. Allows 1 request per 10 seconds per chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Create Chatroom V2

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> contactId is the id field in contact table \</li>\<li> API will create a chatroom or return an existing chatroom for this contact \</li>\<li> Chatroom will be created for the provided Waba and the Phone number if they are registered for this org \</li>\<li> Chatroom's display name will be display name if provided \</li>\<li> Otherwise Chatroom's display name will be contact's crm\_id + FN + LN \</li>\<li> After a certain thresold number of days of inactivity a chatroom is Deactivated. After Deactivation of chatroom, a new chatroom for the same contact with a different crmId can be created\</li>\<li> After a certain thresold number of days of creation a chatroom is Expired. After Expiry of chatroom, a new chatroom for the same contact with a different crmId can be created\</li>\<li> At any point of time only one active chatroom (not deactivated & not expired) can exist for a unique phone number\</li>\<li> On every chatroom creation, a new contact-waba is created if not already present \</li>\<li> Each contact can only have one waba mapping\</li>\<li> Every contact-waba mapping is per Waba per Waba Phone, i.e any contact with same phone can one active chatroom present across multiple Waba Phone(s)\</li>\<li> By default (fail\_if\_chatroom\_exists\_on\_other\_wabaphone = true), in case of an existing contact-waba mapping, we throw a Conflict upon trying to create a chatroom for the same phone number.\</li>\<li> For fail\_if\_chatroom\_exists\_on\_other\_wabaphone = false, we create chatroom with same phone number with the next available Waba Phone.\</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CreateChatroomReqV2Dto":{"required":["contact_id","user_id"],"type":"object","properties":{"user_id":{"type":"string"},"display_name":{"type":"string"},"remote_waba_id":{"type":"string"},"remote_phone_id":{"type":"string"},"contact_id":{"type":"string"},"fail_if_chatroom_exists_on_other_wabaphone":{"type":"boolean"},"assign_on_handover":{"type":"boolean"}}},"ChatroomRespDto":{"type":"object","properties":{"chatroom_id":{"type":"string"},"external_ref_id":{"type":"string"},"is_existing":{"type":"boolean"},"is_deactivated":{"type":"boolean"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"},"deactivation_ts":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v2/org/{orgId}/chatroom":{"post":{"tags":["chatroom-controller"],"summary":"Create Chatroom V2","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> contactId is the id field in contact table </li><li> API will create a chatroom or return an existing chatroom for this contact </li><li> Chatroom will be created for the provided Waba and the Phone number if they are registered for this org </li><li> Chatroom's display name will be display name if provided </li><li> Otherwise Chatroom's display name will be contact's crm_id + FN + LN </li><li> After a certain thresold number of days of inactivity a chatroom is Deactivated. After Deactivation of chatroom, a new chatroom for the same contact with a different crmId can be created</li><li> After a certain thresold number of days of creation a chatroom is Expired. After Expiry of chatroom, a new chatroom for the same contact with a different crmId can be created</li><li> At any point of time only one active chatroom (not deactivated & not expired) can exist for a unique phone number</li><li> On every chatroom creation, a new contact-waba is created if not already present </li><li> Each contact can only have one waba mapping</li><li> Every contact-waba mapping is per Waba per Waba Phone, i.e any contact with same phone can one active chatroom present across multiple Waba Phone(s)</li><li> By default (fail_if_chatroom_exists_on_other_wabaphone = true), in case of an existing contact-waba mapping, we throw a Conflict upon trying to create a chatroom for the same phone number.</li><li> For fail_if_chatroom_exists_on_other_wabaphone = false, we create chatroom with same phone number with the next available Waba Phone.</li></ul>","operationId":"createChatroomV2","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChatroomReqV2Dto"}}},"required":true},"responses":{"200":{"description":"Successfully returning the chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatroomRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or Partner does not have access to this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"OrgId, UserId, Contact or WABA does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"409":{"description":"Active chatroom already exists with a different crmId","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Reassign Chatroom V2

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> This API works only for chatrooms created for waba. Hence explicitly added /waba in the API endpoint \</li>\<li> API will revoke access of all the existing users from the chatroom and add new users to the chatroom \</li>\<li> Depending on the room history visibility flag while creating the chatroom the new users may or may not see messages from the past \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]},{}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ReassignRoomReqV2Dto":{"required":["user_id"],"type":"object","properties":{"user_id":{"type":"string"}}},"ChatroomRespDto":{"type":"object","properties":{"chatroom_id":{"type":"string"},"external_ref_id":{"type":"string"},"is_existing":{"type":"boolean"},"is_deactivated":{"type":"boolean"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"},"deactivation_ts":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v2/org/{orgId}/waba/chatroom/{chatroomId}/reassign":{"post":{"tags":["reassignment-controller"],"summary":"Reassign Chatroom V2","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> This API works only for chatrooms created for waba. Hence explicitly added /waba in the API endpoint </li><li> API will revoke access of all the existing users from the chatroom and add new users to the chatroom </li><li> Depending on the room history visibility flag while creating the chatroom the new users may or may not see messages from the past </li></ul>","operationId":"reassignChatroom","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"chatroomId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReassignRoomReqV2Dto"}}},"required":true},"responses":{"200":{"description":"Successfully reassigned the chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatroomRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"User or Partner does not have access to this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"Chatroom does not exist for this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"429":{"description":"Rate limit exceeded. Allows 1 request per 10 seconds per chatroom","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Internal Exception","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}},"deprecated":true}}}}
```

## Deactivate Chatroom

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: True \</li>\</ul>\<ul>\<li> Message aren't allowed in a deactivated chatroom.\</li>\<li> After a certain threshold of inactivity based on org config a chatroom is marked deactivated \</li>\<li> A deactivated chatroom can be activated \</li>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"DeactivateChatroomReqDto":{"type":"object","properties":{"deactivation_reason":{"type":"string","enum":["LEAD_OPTED_OUT","LEAD_LIFECYCLE_THRESHOLD_EXPIRED","FORCE_DEACTIVATE"]}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/contacts/chatroom/{chatroomId}/deactivate":{"put":{"tags":["chatroom-controller"],"summary":"Deactivate Chatroom","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: True </li><li> Partner Allowed: True </li></ul><ul><li> Message aren't allowed in a deactivated chatroom.</li><li> After a certain threshold of inactivity based on org config a chatroom is marked deactivated </li><li> A deactivated chatroom can be activated </li>","operationId":"deactivateContactChatroom","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"chatroomId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeactivateChatroomReqDto"}}}},"responses":{"202":{"description":"Successfully accepted request for deactivating contact chatroom","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to deactivate chatroom due to some internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Activate Chatroom

> \<ul>\<li> Roles Allowed: ADMIN \</li>\<li> Impersonated User Allowed: False \</li>\<li> Partner Allowed: True \</li>\<li> A flag force\_deactivate is used with false default value \</li>\<li> By default we won't allow activation if any active chatroom already exists with the same phone number \</li>\<li> If force\_deactivate is set to true, then all existing active chatrooms for the same Waba Phone with same pn will be deactivated \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/contacts/chatroom/{chatroomId}/activate":{"put":{"tags":["chatroom-controller"],"summary":"Activate Chatroom","description":"<ul><li> Roles Allowed: ADMIN </li><li> Impersonated User Allowed: False </li><li> Partner Allowed: True </li><li> A flag force_deactivate is used with false default value </li><li> By default we won't allow activation if any active chatroom already exists with the same phone number </li><li> If force_deactivate is set to true, then all existing active chatrooms for the same Waba Phone with same pn will be deactivated </li></ul>","operationId":"activateContactChatroom","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"chatroomId","in":"path","required":true,"schema":{"type":"string"}},{"name":"force_deactivate","in":"query","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"202":{"description":"Successfully accepted request for re-activating contact chatroom","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to activate chatroom due to some internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```

## Get Chatroom by Contact

> \<ul>\<li> Roles Allowed: MEMBER \</li>\<li> Impersonated User Allowed: True \</li>\<li> Partner Allowed: True \</li>\</ul>

```json
{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"https://apis.saleschat.pro"}],"security":[{"bearer-key":[]}],"components":{"securitySchemes":{"bearer-key":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"WabaChatroomRespDto":{"type":"object","properties":{"chatroom_id":{"type":"string"},"external_ref_id":{"type":"string"},"is_existing":{"type":"boolean"},"is_deactivated":{"type":"boolean"},"is_expired":{"type":"boolean"},"expiry_ts":{"type":"string","format":"date-time"},"deactivation_ts":{"type":"string","format":"date-time"},"waba":{"$ref":"#/components/schemas/WabaDto"}}},"WabaDto":{"type":"object","properties":{"remote_waba_id":{"type":"string"},"matrix_host_name":{"type":"string"},"name":{"type":"string"}}},"ErrorRespDto":{"type":"object","properties":{"error_code":{"type":"integer"},"error_message":{"type":"string"},"error_description":{"type":"string"},"payload":{"type":"object"}}}}},"paths":{"/v1/org/{orgId}/chatroom/contact/{contactId}":{"get":{"tags":["chatroom-controller"],"summary":"Get Chatroom by Contact","description":"<ul><li> Roles Allowed: MEMBER </li><li> Impersonated User Allowed: True </li><li> Partner Allowed: True </li></ul>","operationId":"getChatroomByContact","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully fetched chatroom by contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WabaChatroomRespDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"401":{"description":"Unauthorized - Authentication is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"403":{"description":"Forbidden - You don't have permission to access this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"404":{"description":"No contact waba mapping found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"422":{"description":"Required fields are missing or invalid values are provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}},"500":{"description":"Failed to fetch chatroom due to some internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorRespDto"}}}}}}}}}
```


